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
, поскольку он не делает ничего особенного, но мне потребуется больше времени, чтобы разобраться.
С этим awk
awk -v old='TOCHANGE' '
NR==FNR{a[NR]=$0;next}
$2==old{$2=a[++i]}
1' changefile infile > outfile
Сочетайте хитрые решения со специфическими 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
С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
).