我尝试使用sed
或awk
在其他人的文件中更改单词。
我有1个fileA
,像这样:
((A,(B,(C,D))),(E));
((A,B),C),D),(E));
和第二个fileB
,其模式要更改:
A (foo,bar,foox,barn,foon)
B (cat,dog,sheep,abc)
C (cadd,dget,vdhfu,dssu,dfhty,dueit)
D (cdfte,shdgt,cdht,ddht,ddh)
E (cdc,addge)
我想在fileA
中将值A
,B
,C
,D
和E
替换为图案文件。
我的尝试
while read n k; do sed -i.bak "s/$k/$n/g" fileA; done < fileB
答案 0 :(得分:1)
<button onclick="document.getElementById('myImage').src='pic_bulboff.gif'">Turn off the light</button>
内部sed "$(sed 's/^\([^ ]*\) \(.*\)$/s#\1#\2#g/' fileB)" fileA
将行从sed
转换为fileB
。
然后,使用参数作为第一个的输出运行下一个sed。
对于输入文件s/<pattern>/<pattern>/g
,内部fileB
将打印:
sed
可以传递给外部s#A#(foo,bar,foox,barn,foon)#g
s#B#(cat,dog,sheep,abc)#g
s#C#(cadd,dget,vdhfu,dssu,dfhty,dueit)#g
s#D#(cdfte,shdgt,cdht,ddht,ddh)#g
s#E#(cdc,addge)#g
来执行。
在jdoodle上进行了以下测试:
sed
我得到以下输出:
cat <<EOF >fileA
((A,(B,(C,D))),(E));
((A,B),C),D),(E));
EOF
cat <<EOF >fileB
A (foo,bar,foox,barn,foon)
B (cat,dog,sheep,abc)
C (cadd,dget,vdhfu,dssu,dfhty,dueit)
D (cdfte,shdgt,cdht,ddht,ddh)
E (cdc,addge)
EOF
sed "$(sed 's/^\([^ ]*\) \(.*\)$/s#\1#\2#g/' fileB)" fileA
答案 1 :(得分:1)
您也可以尝试Perl。
$ cat nico_fileA
((A,(B,(C,D))),(E));
((A,B),C),D),(E));
$ cat nico_fileB
A (foo,bar,foox,barn,foon)
B (cat,dog,sheep,abc)
C (cadd,dget,vdhfu,dssu,dfhty,dueit)
D (cdfte,shdgt,cdht,ddht,ddh)
E (cdc,addge)
$ perl -pe ' BEGIN { %kv=map{chomp;split} qx(cat nico_fileB) } s/([A-E])/$kv{$1}/g ' nico_fileA
(((foo,bar,foox,barn,foon),((cat,dog,sheep,abc),((cadd,dget,vdhfu,dssu,dfhty,dueit),(cdfte,shdgt,cdht,ddht,ddh)))),((cdc,addge)));
(((foo,bar,foox,barn,foon),(cat,dog,sheep,abc)),(cadd,dget,vdhfu,dssu,dfhty,dueit)),(cdfte,shdgt,cdht,ddht,ddh)),((cdc,addge)));
$
答案 2 :(得分:1)
在这种情况下要担心的一件事情是,替换的值之一是否包含替换的键之一。例如,如果您正在查看原始文本
AfooB
并替换为
A B
B C
您想以BfooC
结尾,但是如果连续进行全文替换,则:
sed -i 's/A/B/g' file
sed -i 's/B/C/g' file
您将获得CfooC
。
因此,一个字符一个字符的方法是最安全的:
Tcl语言使用其string map
命令来完成此操作。这是一个bash实现:
# read fileB into an associative array
# keep track of the keys separately so we can be sure to process them in order
declare -A replacements
declare -a keys
while read -r key value; do
replacements[$key]=$value
keys+=("$key")
done < fileB
# process fileA
while IFS= read -r line; do
new=""
i=0
while (( i < ${#line} )); do
replaced=false
for key in "${keys[@]}"; do
len=${#key}
if [[ ${line:i:len} == "$key" ]]; then
new+=${replacements[$key]}
replaced=true
(( i += len ))
break
fi
done
# did we find a replacement at this point in the string?
# if not, append the character to the new string.
if ! $replaced; then
new+=${line:i:1}
(( i += 1 ))
fi
done
echo "$new"
done < fileA
导致
(((foo,bar,foox,barn,foon),((cat,dog,sheep,abc),((cadd,dget,vdhfu,dssu,dfhty,dueit),(cdfte,shdgt,cdht,ddht,ddh)))),((cdc,addge)));
(((foo,bar,foox,barn,foon),(cat,dog,sheep,abc)),(cadd,dget,vdhfu,dssu,dfhty,dueit)),(cdfte,shdgt,cdht,ddht,ddh)),((cdc,addge)));
答案 3 :(得分:0)
调试bash内容的一种好方法是将其回显:
while read n k; do echo sed -i.bak "s/$k/$n/g" fileA; done < fileB
导致:
sed -i.bak s/(foo,bar,foox,barn,foon)/A/g fileA
sed -i.bak s/(cat,dog,sheep,abc)/B/g fileA
sed -i.bak s/(cadd,dget,vdhfu,dssu,dfhty,dueit)/C/g fileA
sed -i.bak s/(cdfte,shdgt,cdht,ddht,ddh)/D/g fileA
sed -i.bak s/( cdc,addge)/E/g fileA
可以肯定,您打算将A
替换为(foo,bar,foox,barn,foon)
,而不是相反-这就是您所写的内容。
while read n k; do sed -i.bak "s/$n/$k/g" fileA; done < fileB
似乎更像它。
答案 4 :(得分:0)
能否请您尝试以下操作,仅在GNU awk
上进行测试。
awk 'FNR==NR{a[$1]=$2;next} {for(i=1;i<=NF;i++){$i=a[$i]?a[$i]:$i}} 1' FS=" " Input_fileB FS="" OFS= Input_fileA
输出如下。
(((foo,bar,foox,barn,foon),((cat,dog,sheep,abc),((cadd,dget,vdhfu,dssu,dfhty,dueit),(cdfte,shdgt,cdht,ddht,ddh)))),((cdc,addge)));
(((foo,bar,foox,barn,foon),(cat,dog,sheep,abc)),(cadd,dget,vdhfu,dssu,dfhty,dueit)),(cdfte,shdgt,cdht,ddht,ddh)),((cdc,addge)));
答案 5 :(得分:0)
您还可以将fileB
行转换为替换命令(如@KamilCuk的答案所示),并通过将process substitution与sed -f
标志一起使用来将输出处理为文件:>
sed -f <(sed -E 's#([^ ]*) (.*)#s/\1/\2/#' fileB) fileA