Использование bash для объединения команды поиска / замены с эхо - PullRequest
0 голосов
/ 04 марта 2020

У меня есть файл CSV с несколькими значениями до / после, которые я использую для поиска и замены значений в другом большом файле данных (~ 200 МБ).

Я изначально использовал чтение всех oop в каждом до / after value и sed для реализации поиска и замены.

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

Итак, у меня есть два значения:

find="ABC"
replace="DEF"

Затем я инициализировал переменную:

cmd=""

и в l oop я пытался использовать эту команду:

cmd="${cmd}s/${find}/${replace}/g;"

Идея состоит в том, чтобы объединить все в одну длинную строку, например:

"s/FIND1/REP1/g;s/FIND2/REP2/g;s/FIND3/REP3/g; ..." And so on

Тогда я мог бы выполнить команду:

perl -i -p -e ${cmd} TARGET_FILE

Проблема в том, что мой вывод для cmd выглядит действительно странно:

echo ${cmd}
/DEF/g;ABC

Порядок полностью испорчен, я даже пытался установить $ {cmd} в строку типа «test», чтобы увидеть, что было происходит, и выход не меняется. Каким-то образом порядок переменных меняется на противоположный, и начальные буквы "s" не отображаются.

Я попытался использовать printf и получил те же результаты. Я попытался удалить точку с запятой, изменить forward-sla sh, экранировать символы и многое другое, но, похоже, ничего не работает. Может кто-нибудь сказать мне, что происходит с этой командой и почему странное поведение?

1 Ответ

0 голосов
/ 04 марта 2020

Выполнение этого в одной строке не масштабируется. Многократные замены также не эффективны.

Этот однострочный Perl считывает файл csv с шаблонами и заменами (значения «до» и «после») в ha sh %to. Затем он создает регулярное выражение $pat, объединяя все значения "before". Затем он читает файл, в котором он заменяет значения «до» на «после», и выводит результат в выходной файл.

cat > pats.csv <<EOF
FIND1,REP1
FIND2,REP2
FIND3,REP3
EOF

cat > in.txt <<EOF
foo FIND1,FIND2,FIND1
bar FIND2 bar
FIND3
EOF

perl -lpe '
BEGIN {
    %to = map { chomp; split m{,}, $_ }
        do { local @ARGV = q{pats.csv}; <> };
    $pat = join q{|}, keys %to;
    $pat = qr{($pat)};
}
s{$pat}{$to{$1}}gxms;
' in.txt > out.txt

cat out.txt
# Prints this:
foo REP1,REP2,REP1
bar REP2 bar
REP3

...