Bash 如何用不同的模式替换模式列表?
我尝试使用Bash 如何用不同的模式替换模式列表?,bash,awk,sed,Bash,Awk,Sed,我尝试使用sed或awk更改文件中的一些单词 我有一个像这样的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) 我想用模式文件中的值
sed
或awk
更改文件中的一些单词
我有一个像这样的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)
我想用模式文件中的值替换A
、B
、C
、D
和E
中的值
我的尝试:
while read n k; do sed -i.bak "s/$k/$n/g" fileA; done < fileB
读取n k时;do sed-i.bak“s/$k/$n/g”文件a;完成
内部的sed
将fileB
中的行转换为s///g
。
然后运行下一个sed,参数作为第一个sed的输出
对于输入文件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
可以将其传递到外部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
您也可以尝试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)));
$
在这种情况下需要担心的一点是,其中一个替换值是否包含一个replacment键。例如,如果您正在查看原始文本
AfooB
并替换为
A B
B C
您希望以BfooC
结束,但如果您连续进行全文重播:
sed -i 's/A/B/g' file
sed -i 's/B/C/g' file
您将获得CfooC
因此,逐个字符的方法是最安全的:
- 从索引0开始查看每行中的每个位置
- 如果字符串中的任何键在此点匹配,请替换为该键的替换项
- 增加索引并重复
# 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
请尝试以下内容,仅使用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
您还可以将
fileB
行转换为替换命令(如@KamilCuk的回答中所建议),并使用sed-f
标志将输出作为文件处理:
sed -f <(sed -E 's#([^ ]*) (.*)#s/\1/\2/#' fileB) fileA
sed-f出了什么问题?请在您的问题中输入错误/不正确的结果。没有更改,文件是相同的。我还尝试了
sed“s/$k/$n/g”
和sed“s/“$k”/“$n”/g”
也许sed不是最好的工具?将替换哪一个?整个列表,例如(foo、bar等)或任何一个元素?整个列表。可以是很长的一些名单。格式是(Abcd_xyz_x1,Efgh_abcs_y2,Mnho_kjhu_b2)
里面没有空格。很高兴听到这个。。祝你今天愉快@Nico64,你能检查一下这个然后告诉我吗?
(((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)));
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)));
sed -f <(sed -E 's#([^ ]*) (.*)#s/\1/\2/#' fileB) fileA