入力があります。
a
b TOCHANGE
c
d
e TOCHANGE
外部ファイルを使用して「TOCHANGE」モードを変更する必要があります。
line1
line2
...
これにより、次のような結果が得られます。
a
b line1
c
d
e line2
次のコマンドを試しました。
while read k ; do sed -i "s/TOCHANGE/$k/g" input ; done < externalfile
しかし、私は次のようになります。
a
b line1
c
d
e line1
答え1
そして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
拡張正規表現と見なされます。文字通り処理するには(文字列のPAT='TO\.CHANGE'
置換など)、ERE演算子をエスケープする必要があります。TO.CHANGE
答え2
これは、次のようにGNU sedを使用して実行できます。
sed -e '/TOCHANGE/R file_2' input.txt |
sed -e '/TOCHANGE/N;s/TOCHANGE\(.*\)\n\(.*\)/\2\1/'
最初のパスではsedfile_2 行は input.txt のすべての行に対して TOCHANGE 行の下に配置されます。
次のステップでは、TOCHANGE を含む行を次の行に関連付け、as/// 置換で期待される出力を提供します。
そして真珠次のように実装できます。
perl -pe 's|TOCHANGE|<STDIN> =~ s/\n//r|e' input.txt < file_2
答え3
これで
awk -v old='TOCHANGE' '
NR==FNR{a[NR]=$0;next}
$2==old{$2=a[++i]}
1' changefile infile > outfile
答え4
厳しいソリューションとawk
特定の機能を組み合わせてください。
最初の亜種
"TOCHANGE"
パターンが各行で一度だけ発生する場合。普段通りawk
なら十分です。
awk '{
if(NF == 2) {
getline OFS < "file_2"
$1 = $1
}
print
}' FS='TOCHANGE' input.txt
2番目の変形
"TOCHANGE"
パターンが各行に複数回表示される場合。必須gawk
。
gawk '{
RS="\n"
if(RT)
getline ORS < "file_2"
else
ORS=""
print
RS="TOCHANGE"
}' RS='TOCHANGE' input.txt
テスト
入力.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