输入文本文件:file.txt
AAA
BBB_CCC
BBB
AAA BBB
需要得到:
AAA_CCC
BBB_CCC
BBB_CCC
AAA_CCC BBB_CCC
我用以下正则表达式调用sed:
sed "/_CCC/! s/AAA/AAA_CCC/g;/_CCC/! s/BBB/BBB_CCC/g" file.txt > file_out.txt
但它产生:
AAA_CCC
BBB_CCC
BBB_CCC
AAA_CCC BBB
一种解决方案是在同一个文件上调用sed两次,但我认为存在一种更优雅的方式。
一种方法是系统地覆盖_CCC
,如果它存在:
sed 's/\(AAA\|BBB\)\(_CCC\)\?/\1_CCC/g' file
使用ERE:
sed -E 's/(AAA|BBB)(_CCC)?/\1_CCC/g' file
一个与您精神接近的解决方案:
$ sed -E '/_CCC/!s/(AAA|BBB)/\1_CCC/g' infile
AAA_CCC
BBB_CCC
BBB_CCC
AAA_CCC BBB_CCC
您的解决方案失败,因为在最后一行插入_CCC
后,/_CCC/!
检查失败:字符串现在完全存在。我的解决方案只使用一个替换命令就可以避免这个问题。
awk
解决方案将_CCC
附加到不包含它的每个字段:
awk '{ for(i=1; i<=NF; i++) if( $i !~ /_CCC$/ ) $i = $i"_CCC"; }1' file
#output:
AAA_CCC
BBB_CCC
BBB_CCC
AAA_CCC BBB_CCC
另一个awk
$ awk -v RS=' +|\n' '{sub("(_CCC|)$","_CCC"); ORS=RT}1' file
AAA_CCC
BBB_CCC
BBB_CCC
AAA_CCC BBB_CCC
又一个sed解决方案:
$ sed 's/\(_CCC\)*\( \|$\)/_CCC\2/g' file
AAA_CCC
BBB_CCC
BBB_CCC
AAA_CCC BBB_CCC