Rob*_*hoy 5 sed awk perl text-processing
我正在尝试替换 a 中的字符串file A
:
Hello Peter, how is your dad? where is mom?
Run Code Online (Sandbox Code Playgroud)
要替换的字符串在file B
:
Peter
dad
mom
Run Code Online (Sandbox Code Playgroud)
和他们相应的替代品在file C
:
John
wife
grandpa
Run Code Online (Sandbox Code Playgroud)
预期结果:
Hello John, how is your wife? where is grandpa?
Run Code Online (Sandbox Code Playgroud)
我可以编辑file A
,file B
使用 in 中相应行中的值替换 in中的值file C
吗?
到目前为止我做了什么:
cat 1.txt | sed -e "s/$(sed 's:/:\\/:g' 2.txt)/$(sed 's:/:\\/:g' 3.txt)/" > 4.txt
Run Code Online (Sandbox Code Playgroud)
如果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
Run Code Online (Sandbox Code Playgroud)
那sed
然后将执行,编辑fileA
。的适当的方式是处理LHS
/RHS
第一和逃脱这些线路可能出现的任何特殊字符,然后加入LHS
和RHS
加入s
,分隔符/
和g
(例如用paste
)和管道将结果sed
:
paste -ds///g /dev/null /dev/null \
<(sed 's|[[\.*^$/]|\\&|g' fileB) <(sed 's|[\&/]|\\&|g' fileC) \
/dev/null /dev/null | sed -f - fileA
Run Code Online (Sandbox Code Playgroud)
所以它是:一个paste
和三个sed
s 将只处理每个文件一次,而不管行数如何。
这假设您的 shell 支持进程替换,并且您sed
可以从stdin读取脚本文件。此外,它不会就地编辑(我忽略了开关,因为它不受所有s支持)-i
sed
我创建的解决方案不是很短,但足够简单,非常易读。除非你的任务是用 sed 完成整个事情...?
#!/usr/bin/bash
cp A.txt D.txt
x=1
length=$(wc -l B.txt | sed 's/\ .*//g')
until [ $x -eq $length ]; do
Bx=$(awk "NR==$x" B.txt)
Cx=$(awk "NR==$x" C.txt)
sed -i "s/$Bx/$Cx/g" D.txt
x=$(($x+1))
done
rm -f ./sed*
Run Code Online (Sandbox Code Playgroud)
请注意,如果 B.txt 比 C.txt 长,则此脚本会创建大量垃圾文件,反之亦然(没有测试那么远)