оптимизация sed (большая модификация файла на основе меньшего набора данных)

Вы должны использовать скрипт лайтбокса, например fancybox ( https://fancyapps.com/fancybox/3/ ), вам просто нужно добавить атрибуты data-fancybox для ссылок, например: [ 114]

Также возможно заставить его работать без ссылок - https://codepen.io/anon/pen/rRVeJW

8
задан Brian Tompsett - 汤莱恩 5 November 2015 в 10:12
поделиться

6 ответов

Мои предлагаемые подходы (в желаемом порядке) заключаются в обработке этих данных как:

  1. База данных ( даже простая база данных на основе SQLite с индексом будет работать намного лучше, чем sed / awk с файлом размером 10 ГБ)
  2. Плоский файл с фиксированной длиной записи
  3. Плоский файл, содержащий записи переменной длины

Использование базы данных требует заботиться обо всех тех мелких деталях, которые замедляют обработку текстового файла (поиск нужной записи, изменение данных, сохранение их обратно в БД). Взгляните на DBD :: SQLite в случае Perl.

Если вы хотите придерживаться плоских файлов, вы захотите вручную поддерживать индекс вместе с большим файлом, чтобы вам было легче найти номера записей, которые вы нужно будет манипулировать. Или, еще лучше, возможно, ваши идентификационные номера являются вашими номерами записей?

Если у вас есть записи переменной длины, я бы предложил преобразовать их в записи фиксированной длины (поскольку оказывается, что только ваш идентификатор имеет переменную длину). Если вы не можете этого сделать, возможно, какие-либо существующие данные никогда не будут перемещаться в файле? Затем вы можете поддерживать этот ранее упомянутый индекс и добавлять новые записи по мере необходимости, с той разницей, что вместо индекса, указывающего на номер записи, вы теперь указываете на абсолютную позицию в файле.

возможно, какие-либо существующие данные никогда не будут перемещаться в файле? Затем вы можете поддерживать этот ранее упомянутый индекс и добавлять новые записи по мере необходимости, с той разницей, что вместо индекса, указывающего на номер записи, вы теперь указываете на абсолютную позицию в файле.

возможно, какие-либо существующие данные никогда не будут перемещаться в файле? Затем вы можете поддерживать этот ранее упомянутый индекс и добавлять новые записи по мере необходимости, с той разницей, что вместо индекса, указывающего на номер записи, вы теперь указываете на абсолютную позицию в файле.

6
ответ дан 5 December 2019 в 14:06
поделиться

, я предлагаю вам программу, написанную на Perl (поскольку я не гуру sed / awk, и я не знаю, на что они в точности способны).

Ваш "алгоритм" прост: вам нужно, прежде всего, построить хэш-карту, которая могла бы дать вам новую строку данных для применения для каждого идентификатора. Конечно, это достигается чтением файла модификатора.

После того, как эта hasmap заполнена, вы можете просматривать каждую строку вашего файла данных, читать идентификатор в середине строки и генерировать новую строку, как вы описали выше.

Я тоже не гуру Perl, но считаю, что программа довольно проста. Если вам нужна помощь в написании, попросите: -)

3
ответ дан 5 December 2019 в 14:06
поделиться

В perl вы должны использовать substr для получения id_number, особенно если id_number имеет постоянную ширину.

my $id_number=substr($str, 500, id_number_length);

После этого, если $ id_number находится в диапазоне, вы должны использовать substr для замены оставшегося текста.

substr($str, -300,300, $new_text);

Регулярные выражения Perl работают очень быстро, но не в этом случае.

2
ответ дан 5 December 2019 в 14:06
поделиться

Я предлагаю не использовать базу данных. Хорошо написанный скрипт Perl превосходит базу данных по порядку величины в задачах такого рода. Поверьте, у меня много практического опыта с этим. Вы не будете импортировать данные в базу данных, когда Perl будет завершен.

Когда вы напишете 1500000 строк с 800 символами, мне кажется, что это 1,2 ГБ. Если у вас очень медленный диск (30 МБ / с), вы прочитаете его за 40 секунд. Лучше 50 -> 24 с, 100 -> 12 и так далее. Но скорость поиска хэша perl (например, db join) на ЦП с частотой 2 ГГц превышает 5 Mlookups / s. Это означает, что ваша работа, связанная с ЦП, будет в секундах, а ваша работа, связанная с вводом-выводом, будет за десятки секунд. Если это действительно 10 ГБ, номера изменятся, но пропорция останется прежней.

Вы не указали, изменяет ли модификация данных размер или нет (если модификация может быть сделана на месте), поэтому мы не будем предполагать это и будем работать как фильтр. Вы не указали, в каком формате находится ваш «файл модификаторов» и какие модификации. Предположим, что они разделены табуляцией, например:

<id><tab><position_after_id><tab><amount><tab><data>

Мы будем читать данные из стандартного ввода и записывать в стандартный вывод, а сценарий может выглядеть примерно так:

my $modifier_filename = 'modifier_file.txt';

open my $mf, '<', $modifier_filename or die "Can't open '$modifier_filename': $!";
my %modifications;
while (<$mf>) {
   chomp;
   my ($id, $position, $amount, $data) = split /\t/;
   $modifications{$id} = [$position, $amount, $data];
}
close $mf;

# make matching regexp (use quotemeta to prevent regexp meaningful characters)
my $id_regexp = join '|', map quotemeta, keys %modifications;
$id_regexp = qr/($id_regexp)/;     # compile regexp

while (<>) {
  next unless m/$id_regexp/;
  next unless $modifications{$1};
  my ($position, $amount, $data) = @{$modifications{$1}};
  substr $_, $+[1] + $position, $amount, $data;
}
continue { print }

На моем ноутбуке требуется около полминуты для 1,5 миллиона строк, 1800 идентификаторов поиска. , 1,2 ГБ данных. Для 10 ГБ это не должно превышать 5 минут. Разумно ли это быстро для вас?

Если вы начинаете думать, что не привязаны к вводу-выводу (например, если используете какой-то NAS), но привязаны к ЦП, вы можете пожертвовать некоторой удобочитаемостью и изменить это:

my $mod;
while (<>) {
  next unless m/$id_regexp/;
  $mod = $modifications{$1};
  next unless $mod;
  substr $_, $+[1] + $mod->[0], $mod->[1], $mod->[2];
}
continue { print }
1
ответ дан 5 December 2019 в 14:06
поделиться

Вы почти наверняка должны использовать базу данных, как предложил MikeyB .

Если вы по какой-то причине не хотите использовать базу данных, то если список модификации умещаются в памяти (как сейчас в 1800 строках), наиболее эффективным методом является хеш-таблица, заполненная модификациями, как предлагает Ив Бомес .

Если вы дойдете до точки, где даже список модификаций становится огромным, вам нужно отсортировать оба файла по их идентификаторам, а затем выполнить слияние списков - в основном:

  1. Сравните идентификатор вверху входного файла с идентификатором на "верх" файла модификаций
  2. Отрегулируйте запись соответствующим образом, если они совпадают.
  3. Запишите ее
  4. Отбросьте "верх"строки из любого файла, имеющего (в алфавитном или числовом порядке) наименьший идентификатор, и прочитать другую строку из этого файла
  5. Перейти к 1.

За кулисами база данных почти наверняка будет использовать объединение списков, если вы выполните это изменение с помощью одного Команда SQL UPDATE .

0
ответ дан 5 December 2019 в 14:06
поделиться

Хорошая сделка по выбору sqlloader или datadump. Это правильный путь.

0
ответ дан 5 December 2019 в 14:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: