Text-Processing
根據字元串列表和相應替換列表替換文件中的字元串
我正在嘗試替換 a 中的字元串
file A
:Hello Peter, how is your dad? where is mom?
要替換的字元串在哪裡
file B
:Peter dad mom
並且它們相應的替換在
file C
:John wife grandpa
預期結果:
Hello John, how is your wife? where is grandpa?
我可以編輯,通過使用相應行中的值
file A
替換中的值嗎?file B``file C
到目前為止我做了什麼:
cat 1.txt | sed -e "s/$(sed 's:/:\\/:g' 2.txt)/$(sed 's:/:\\/:g' 3.txt)/" > 4.txt
如果
file B
&中只有file C
一行,它可以工作,如果有多行,它將不起作用。
最簡單的方法
sed
是處理這兩個列表並將它們轉換為*腳本文件,*例如s/line1-from-fileB/line1-from-fileC/g s/line2-from-fileB/line2-from-fileC/g .................................... s/lineN-from-fileB/lineN-from-fileC/g
然後將
sed
執行,編輯fileA
. 正確的方法是先處理LHS
/RHS
並轉義可能出現在這些行上的任何特殊字元,然後加入LHS
並RHS
添加s
、分隔符/
和g
(例如 withpaste
)並將結果通過管道傳輸到sed
:paste -ds///g /dev/null /dev/null \ <(sed 's|[[\.*^$/]|\\&|g' fileB) <(sed 's|[\&/]|\\&|g' fileC) \ /dev/null /dev/null | sed -f - fileA
就是這樣:一個
paste
和三個sed
s 將只處理每個文件一次,而不管行數如何。這假設您的 shell 支持程序替換,並且您可以從stdin
sed
讀取腳本文件。此外,它不會就地編輯(我省略了開關,因為所有s 都不支持它)-i``sed
如果您希望替換彼此獨立完成,例如:
foo -> bar bar -> foo
應用於
foobar
以導致:
barfoo
與
foofoo
天真的s/foo/bar/g; s/bar/foo/g
翻譯相反,您可以這樣做:perl -pe ' BEGIN{ open STRINGS, "<", shift@ARGV or die"STRINGS: $!"; open REPLACEMENTS, "<", shift@ARGV or die "REPLACEMENTS: $!"; while (defined($a=<STRINGS>) and defined($b=<REPLACEMENTS>)) { chomp ($a, $b); push @repl, $b; push @re, "$a(?{\$repl=\$repl[" . $i++. "]})" } eval q($re = qr{) . join("|", @re) . "}"; } s/$re/$repl/g' strings.txt replacements.txt fileA
這是
perl
預期的正則表達式patterns.txt
。由於 perl 正則表達式可以執行任意程式碼,因此對它們進行清理很重要。如果只想替換固定字元串,可以將其更改為:perl -pe ' BEGIN{ open PATTERNS, "<", shift@ARGV or die"PATTERNS: $!"; open REPLACEMENTS, "<", shift@ARGV or die "REPLACEMENTS: $!"; for ($i = 0; defined($a=<PATTERNS>) and defined($b=<REPLACEMENTS>); $i++) { chomp ($a, $b); push @string, $a; push @repl, $b; push @re, "\\Q\$string[$i]\\E(?{\$repl=\$repl[$i]})" } eval q($re = qr{) . join("|", @re) . "}"; } s/$re/$repl/g' patterns.txt replacements.txt fileA