Быстрый способ замены пар строк в файле

У меня есть файл с ~ 10 000 строк, содержащий 2 столбца:

org_string1 \t replacement_string1
org_string2 \t replacement_string2

Каков наилучший способ (скорость/удобство) заменить все эти org_string на соответствующие им replace_string в другом текстовом файле (выполнив замену 10k во втором файле)?

Я планирую преобразовать их в команду подстановки sed, но не уверен в скорости работы и в том, превысит ли она максимальный предел командной строки в Linux.

Предположение:

  1. Все org_string и replace_string уникальны.
  2. org_string — это одно слово (окруженное пробелом) во входном файле.

person Ken    schedule 12.07.2016    source источник
comment
Итак, вы хотите сделать 10 тысяч различных замен во втором файле? По моему опыту, sed будет очень медленным, даже если вы дадите ему файл с 10k s/org_string1/replacement_string1/ строк. Я не пробовал Perl или Python с 10-тысячным словарем регулярных выражений и замен.   -  person    schedule 12.07.2016
comment
Я предполагаю, что конвертировать/заменять в Perl не составит труда, поскольку Perl сделает это за миллисекунды.   -  person ssr1012    schedule 12.07.2016
comment
Одиночная замена будет быстрой. Но проверка каждой строки по 10 тысячам шаблонов подведет итог.   -  person    schedule 12.07.2016
comment
Быстрая замена текста в очень большом файле [StackExchange] unix.stackexchange.com/questions/255373/   -  person ssr1012    schedule 12.07.2016
comment
@ ssr1012 Вопрос, на который вы ссылаетесь, заключается не в том, чтобы выполнить 10 000 различных замен, возможно, в каждой строке файла. Проблема здесь в большом количестве замен.   -  person    schedule 12.07.2016
comment
@FullName Ваш словарь не обязательно должен содержать регулярные выражения, подойдут простые строки.   -  person Michael Vehrs    schedule 12.07.2016


Ответы (1)


Вот техника с использованием Perl, которая может помочь:

my %map = (
    'the'   => 'a',
    'fox'   => 'frog',
    'jumps' => 'somersaults'
);

my $line = "the quick bown fox jumps over the lazy dog";

$line =~ s{\b(\w+)\b}{$map{$1} // $1}eg;

say $line;

В этом примере используется жестко запрограммированное сопоставление хэша orig_strings с replace_strings — в вашем случае вы должны заполнить этот хэш сопоставления, прочитав файл пар сопоставления.

Затем регулярное выражение использует \b(\w+)\b для захвата каждого слова в строке и перехода на сторону замены через $1. Поскольку указана опция /e, правая часть подстановки обрабатывается как выражение Perl, а результатом вычисления выражения является замещающий текст. $map{$1} использует исходное слово в качестве ключа к хэшу сопоставления для поиска замещающего текста. Часть // $1 говорит, что если поиск хеша возвращает undef (т. е. для этого слова нет замены), то просто используйте исходный текст.

Часть \w+ будет соответствовать строке слова, цифры или символа подчеркивания. Вам могут понадобиться только буквенные символы и, возможно, апострофы и дефисы. Для этого используйте [a-zA-Z'-]+ вместо \w+.

Это должно быть очень быстро, потому что в каждой строке выполняется только одно регулярное выражение и только один поиск хеша для каждого слова в каждой строке.

person Grant McLean    schedule 12.07.2016
comment
Это намного быстрее, чем делать множественную замену. Спасибо. - person Ken; 13.07.2016