Нахождение и замена многих слов - PullRequest
5 голосов
/ 23 ноября 2011

Мне часто приходится делать много замен в файлах.Чтобы решить эту проблему, я создал два файла old.text и new.text.Первый содержит список слов, которые необходимо найти.Второй содержит список слов, которые должны заменить их.

  • Все мои файлы используют UTF-8 и используют различные языки.

Я создал этот скрипт, который я надеялся сделать замену.Сначала он читает old.text по одной строке за раз, а затем заменяет слова в этой строке в файле input.txt соответствующими словами из файла new.text.

#!/bin/sh
number=1
while read linefromoldwords
do
    echo $linefromoldwords
    linefromnewwords=$(sed -n '$numberp' new.text)
    awk '{gsub(/$linefromoldwords/,$linefromnewwords);print}' input.txt >> output.txt
    number=$number+1
echo $number
done <  old.text

Однако мое решение не позволяетхорошо работать.Когда я запускаю скрипт:

  • В строке 6 команда sed не знает, где заканчивается $number.
  • Переменная $number меняется на "0+1 ", затем" 0 + 1 + 1 ", когда он должен измениться на" 1 ", затем" 2 ".
  • Строка с awk, похоже, не делает ничего, кроме копированияinput.txt точно такой же, как и output.txt.

У вас есть предложения?

Обновление:

Отмеченный ответ работает хорошо, однако я используюЭтот сценарий много, и это займет много часов, чтобы закончить.Поэтому я предлагаю вознаграждение за решение, которое может выполнить эти замены намного быстрее.Решение в BASH, Perl или Python 2 будет в порядке, при условии, что оно по-прежнему совместимо с UTF-8.Если вы думаете, что какое-то другое решение, использующее другое программное обеспечение, обычно доступное в системах Linux, будет быстрее, то это тоже может быть хорошо, если не требуются огромные зависимости.

Ответы [ 12 ]

1 голос
/ 11 декабря 2011

Это должно сократить время некоторыми способами, поскольку это позволяет избежать ненужных циклов.

Объединение двух входных файлов:

Предположим, у вас есть два входных файла, old.text , содержащих все подстановки и new.text содержит все замен .

Мы создадим новый текстовый файл, который будет действовать как sed script для вашего основного файла, используя следующую awk однострочник:

awk '{ printf "s/ "$0" /"; getline <"new.text"; print " "$0" /g" }' old.text > merge.text 

[jaypal:~/Temp] cat old.text 
19
20

[jaypal:~/Temp] cat new.text 
A
B

[jaypal:~/Temp] awk '{ printf "s/ "$0" /"; getline <"new.text"; print " "$0" /g" }' old.text > merge.text

[jaypal:~/Temp] cat merge.text 
s/ 19 / A /g
s/ 20 / B /g

Примечание: Это форматирование замены и замены основано на вашем требовании иметь пробелы между словами.

Использование объединенного файла в качестве сценария sed:

Как только ваш объединенный файл имеетМы создали утилиту -f option из sed.

sed -f merge.text input_file

[jaypal:~/Temp] cat input_file 
 12 adsflljl
 12 hgfahld
 12 ash;al
 13 a;jfda
 13 asldfj
 15 ;aljdf
 16 a;dlfj
 19 adads
 19 adfasf
 20 aaaadsf

[jaypal:~/Temp] sed -f merge.text input_file 
 12 adsflljl
 12 hgfahld
 12 ash;al
 13 a;jfda
 13 asldfj
 15 ;aljdf
 16 a;dlfj
 A adads
 A adfasf
 B aaaadsf

Вы можете перенаправить ее в другой файл с помощью оператора >.

1 голос
/ 23 ноября 2011

В строке 6 команда sed не знает, где заканчивается число $.

linefromnewwords=$(sed -n '${number}p' newwords.txt)

Я не уверен в цитировании, но $ {number} pработа - возможно, "$ {число} p"

Переменная $ number меняется на "0 + 1", затем на "0 + 1 + 1", когда она должна измениться на "1",тогда "2".

Арифметическая целочисленная оценка в bash может быть выполнена с помощью $ (()) и лучше, чем eval (eval = evil).

number=$((number + 1))

В общем, я бы рекомендовал использовать один файл с

s/ ni3 / nǐ /g
s/ nei3 / neǐ /g

и так далее, по одной sed-команде на строку, о чем лучше позаботиться - сортируйте по алфавиту и используйте с:

sed -f translate.sed input > output 

Таким образом, вы всегда можете легко сравнить сопоставления.

s/\bni3\b/nǐ/g

может быть предпочтительнее пробелов в качестве явных разделителей, поскольку \b:=word boundary соответствует началу / концу строки и знакам препинания.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...