如何用不包含同一行的特定字符串替换文本?

时间:2017-12-18 19:18:23

标签: regex bash sed

输入文本文件:file.txt

AAA
BBB_CCC
BBB
AAA BBB

需要获得:

AAA_CCC
BBB_CCC
BBB_CCC
AAA_CCC BBB_CCC

我用以下regexp调用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两次,但我认为存在一种更优雅的方式。

5 个答案:

答案 0 :(得分:4)

一种方法是系统地覆盖_CCC(如果存在):

sed 's/\(AAA\|BBB\)\(_CCC\)\?/\1_CCC/g' file

使用ERE:

sed -E 's/(AAA|BBB)(_CCC)?/\1_CCC/g' file

答案 1 :(得分:2)

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

答案 2 :(得分:2)

在精神上接近你的解决方案:

$ sed -E '/_CCC/!s/(AAA|BBB)/\1_CCC/g' infile
AAA_CCC
BBB_CCC
BBB_CCC
AAA_CCC BBB_CCC

您的解决方案失败,因为在最后一行插入_CCC后,/_CCC/!检查失败:字符串现在完全存在。我的解决方案只使用一个替换命令就可以避免这个问题。

答案 3 :(得分:2)

另一个awk

$ awk -v RS=' +|\n' '{sub("(_CCC|)$","_CCC"); ORS=RT}1' file

AAA_CCC
BBB_CCC
BBB_CCC
AAA_CCC BBB_CCC

答案 4 :(得分:0)

另一种解决方案:

$ sed 's/\(_CCC\)*\( \|$\)/_CCC\2/g' file
AAA_CCC
BBB_CCC
BBB_CCC
AAA_CCC BBB_CCC
相关问题