Заменять каждый раз шаблон другой строкой (взятой из внешнего файла)

perl -lane 'sub flip { if ($_[0] eq "T") { "A" } elsif ($_[0] eq "A") { "T" } elsif ($_[0] eq "G") { "C" } elsif ($_[0] eq "C") { "G" } else { $_[0] } } if (!($F[1] eq $F[2] or $F[1] eq $F[3])) { $F[2] = flip($F[2]); $F[3] = flip($F[3]) } print "@F"' < input

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

4
21.11.2018, 00:39
3 ответа

С этим awk

awk -v old='TOCHANGE' '
NR==FNR{a[NR]=$0;next}
$2==old{$2=a[++i]}
1' changefile infile > outfile
1
27.01.2020, 20:47

Сочетайте хитрые решения со специфическими awkфункциями.

Первый вариант

Если шаблон "TOCHANGE"встречается только один раз в каждой строке. Обычного awkбудет достаточно.

awk '{
    if(NF == 2) {
        getline OFS < "file_2"
        $1 = $1
    }    
    print
}' FS='TOCHANGE' input.txt

Второй вариант

Если шаблон "TOCHANGE"может встречаться много раз в каждой строке. Требуется gawk.

gawk '{
    RS="\n"
    if(RT)
        getline ORS < "file_2"
    else
        ORS=""

    print

    RS="TOCHANGE"
}' RS='TOCHANGE' input.txt

Тестирование

input.txt

a
b TOCHANGE
c
d 
e TOCHANGE
f
g TOCHANGE

файл _2

line1
line2
line3
line4

Выход

a
b line1
c
d 
e line2
f
g line3
1
27.01.2020, 20:47

Сperl:

perl -pi -e 's{TOCHANGE}{chomp ($repl = <STDIN>); $repl}ge' input <externalfile

С помощью awk,предполагая, что TOCHANGEне встречается вexternalfile(или, в более общем случае, замены не генерируют новых вхождений TOCHANGE, что также может произойти, например, на входе, который содержит TOTOCHANGE FROMTOCHANGE, а externalfileсодержит CHANGEиWHATEVER):

POSIXLY_CORRECT=1 PAT=TOCHANGE awk '
  {
    while ($0 ~ ENVIRON["PAT"]) {
      getline repl < "externalfile"
      gsub(/[&\\]/, "\\\\&", repl)
      sub(ENVIRON["PAT"], repl)
    }
    print
  }' < input > input.new

(POSIXLY_CORRECT=1необходим для GNU awk, без которого он не будет работать правильно для строк замены, содержащих символы обратной косой черты ).

Обратите внимание, что $PATвыше рассматривается как расширенное регулярное выражение. Вам может понадобиться экранировать операторы ERE, если вы хотите, чтобы они обрабатывались буквально (как PAT='TO\.CHANGE'для замены строк TO.CHANGE).

6
27.01.2020, 20:47

Теги

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