2017-12-06 8 views
1

neu zu Regex und ein Problem haben. Ich möchte Bindestriche durch Unterstriche an bestimmten Stellen in einer Datei ersetzen. Um die Dinge zu vereinfachen, nehmen wir an, ich möchte den ersten Bindestrich ersetzen. Hier ist ein Beispiel „Datei“:Sed ersetzen Bindestrich mit Unterstrich

dont-touch-these-hyphens 
leaf replace-these-hyphens 

Ich möchte Bindestriche in allen Linien von

grep -P "leaf \w+-" file 

Ich versuchte

sed -i 's/leaf \(\w+\)-/leaf \1_/g' file 

gefunden ersetzen, aber es passiert nichts (falsch Ersatz besser gewesen wäre, als nichts). Ich habe ein paar Verbesserungen versucht, aber immer noch nichts. Auch hier bin ich neu, daher denke ich, dass das obige "im Prinzip funktionieren sollte". Was ist daran falsch, und wie bekomme ich, was ich will? Vielen Dank.

+3

Sie verwenden nicht die Regex-Erweiterungen, die '\ w' unterstützen. Sie brauchen 'sed-E' oder' sed -r'. – stevesliva

+0

Gefällt mir? 'sed -i -E 's/leaf (\ w +) \ -/leaf \ 1_/g' Datei' –

+1

@stevesliva GNU sed versteht' \ w' einfach so. Für GNU sed ist der einzige Unterschied zwischen 'sed' und' sed-E' (oder 'sed-r'), was Sie zu entkommen haben. Siehe auch [das Handbuch] (https://www.gnu.org/software/sed/manual/sed.html#regexp-extensions). –

Antwort

4

Sie können die Dinge vereinfachen, indem Sie zwei verschiedene Regex verwenden; eine für das Abgleichen der Zeilen, die verarbeitet werden müssen, und eine für das Abgleichen, was geändert werden muss.

Sie können so etwas wie dies versuchen:

$ sed '/^leaf/ s/-/_/' file 
dont-touch-these-hyphens 
leaf replace_these-hyphens 
+0

Ordentlich! Wie funktioniert das überhaupt? Dieser erste Teil ist "Passe nicht zu den Buchstaben' leaf' ", wenn ich mich nicht irre, aber anders als das? –

+2

Für Linien, die mit Blatt beginnen, den Ersatz vornehmen. – stevesliva

+2

@ErikVesterlund Hier ist '^' der "Start der Zeile" -Anker, keine Negation wie in einer Zeichenklasse. –

1

Nur awk verwenden:

$ awk '$1=="leaf"{ sub(/-/,"_",$2) } 1' file 
dont-touch-these-hyphens 
leaf replace_these-hyphens 

es Ihnen viel präzisere Steuerung gibt über, was Sie passende (zB die oben einen String tut anstelle von regexp Vergleich auf "Blatt" und so würde funktionieren, selbst wenn diese Zeichenfolge enthalten Regexp Metazeichen wie . oder *) und was Sie ersetzen (zB das obige nur die Ersetzung im Text nach leaf und so würde co ntinue zu arbeiten, auch wenn leaf selbst - s enthalten):

$ cat file 
dont-touch-these-hyphens 
leaf-foo.*bar replace-these-hyphens 
leaf-foobar dont-replace-these-hyphens 

korrekte Ausgabe:

$ awk '$1=="leaf-foo.*bar"{ sub(/-/,"_",$2) } 1' file 
dont-touch-these-hyphens 
leaf-foo.*bar replace_these-hyphens 
leaf-foobar dont-replace-these-hyphens 

Falsche Ausgabe:

$ sed '/^leaf-foo.*bar/ s/-/_/' file 
dont-touch-these-hyphens 
leaf_foo.*bar replace-these-hyphens 
leaf_foobar dont-replace-these-hyphens 

(beachten Sie die "-" in Blatt-foo ist ersetzt durch "_" in jeder der letzten 2 Zeilen, einschließlich derjenigen, die nicht mit der Zeichenkette "leaf-foo. * bar" beginnt.

Dieses awk-Skript wird so funktionieren, wie es ist, mit einem beliebigen awk in einer beliebigen UNIX-Box.

Verwandte Themen