2017-12-18 10 views
0

Eingangstextdatei: datei.txtWie ersetzt man den Text, indem er keine bestimmte Zeichenfolge mit der gleichen Zeile enthält?

AAA 
BBB_CCC 
BBB 
AAA BBB 

Sie benötigen zu bekommen:

AAA_CCC 
BBB_CCC 
BBB_CCC 
AAA_CCC BBB_CCC 

ich das mit folgenden regexp sed nennen:

sed "/_CCC/! s/AAA/AAA_CCC/g;/_CCC/! s/BBB/BBB_CCC/g" file.txt > file_out.txt 

Aber es produziert:

AAA_CCC 
BBB_CCC 
BBB_CCC 
AAA_CCC BBB 

Eine Lösung ruft sed zweimal in derselben Datei auf, aber ich denke, dass es einen eleganteren Weg gibt.

+1

Haben Sie '_CCC' jedes Feld angehängt werden sollen oder nur auf Felder' AAA' und 'BBB'? Mit anderen Worten, was ist, wenn Sie das Feld 'DDD' haben, oder was, wenn Sie das Feld' BBB_CCC_BBB' haben? – PesaThe

Antwort

2

awk Lösung, die _CCC jedem Feld anhängen will, daß es enthält nicht:

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 
4

Eine Möglichkeit besteht _CCC systematisch zu überschreiben, wenn es vorhanden ist:

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

Mit ERE:

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

Eine Lösung das ist die Nähe von Ihnen im Geist:

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

Ihre Lösung schlägt fehl, da nach _CCC in der letzten Zeile eingefügt, die /_CCC/! Prüfung fehlschlägt: die Saite jetzt gibt es doch. Meine Lösung vermeidet dieses Problem, indem sie nur einen einzigen Ersetzungsbefehl verwendet.

2

andere awk

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

AAA_CCC 
BBB_CCC 
BBB_CCC 
AAA_CCC BBB_CCC 
0

Noch eine weitere sed Lösung:

$ sed 's/\(_CCC\)*\(\|$\)/_CCC\2/g' file 
AAA_CCC 
BBB_CCC 
BBB_CCC 
AAA_CCC BBB_CCC 
Verwandte Themen