2017-12-30 107 views
0

Gerade habe ich heute aus einer alten Frage gelernt, wie SED für einzelne Zeilen funktioniert. Aber jetzt versuche ich dasselbe für mehrere Zeilen (php Datei eingerückt) und es funktioniert nicht. Wie soll das gemacht werden?sed - Mehrere Zeilen suchen und ersetzen

Code:

if (empty($donot_dump)) { 
       return false; 

ersetzen:

if (empty($donot_dump)) { 
       return true; 

Dateiname: Klasse-prompt.php

Da dies eine große Datei ist, gibt es TONNEN return false; und zurück wahr ;. Deshalb kann ich nicht einfach alles richtig machen oder umgekehrt.

+1

Bearbeiten Sie Ihre Frage und erklären Sie, warum 'sed 's/false/true /' file 'nicht genug für Ihren Fall ist ... –

+0

Erledigt. Es ist eine große Datei (und es wird mehr Dateien mit demselben "Problem" geben). – Diego

Antwort

5
sed '/if (empty($donot_dump))/ { N; s/false/true/ }' data 
  • /regex/ cmdcmd nur ausführen, wenn die Linie, die die Spiele regex
  • { cmds } ist eine Gruppe von Befehlen
  • N Befehl nächste Zeile aus einer Datei in den Musterraum
  • s/regex/replacement/ Ersatz anhängt regex für replacement

In anderen Worten, diese sed prüft für Ihre gewünschte if Aussage. Wenn es gefunden wird, führt es eine Gruppe von Befehlen innerhalb von { ... } aus. Der erste Befehl N hängt die nächste Zeile an den Musterbereich und der zweite Befehl s ersetzt false für true.


Diese Lösung funktioniert für GNU sed. Wie in SigmaPiEpsilons answer, N Befehl hier nicht erforderlich ist, verwenden Sie es mit Vorsicht. Ich habe es für n verwendet, weil es Ihnen Optionen gibt, von denen ich dachte, dass sie nützlich sein könnten. Sie können mehr darüber in sed manual oder in diesem sed tutorial lesen.

+0

Oh danke :) Und nebenbei funktioniert es: D – Diego

+0

Danke für die Erklärung. Aber du hast gesagt:/regex/cmd, aber wo ist das Cmd (außerhalb "/ /")? Alles andere habe ich verstanden :) – Diego

+1

@Diego Es muss kein einziger Befehl sein. Sie können auch eine Gruppe von Befehlen mit '{cmds}' ausführen. Nach '/ .. /' führt 'sed' zwei Befehle aus, 'N' und' s/false/true'. – PesaThe

0

Eine Vorsichtsmaßnahme über sed multiline N und Alternativen für Menschen mit ähnlichen Problemen. Die mehrzeilige Version von sed N command ist hier nicht wirklich notwendig. Da der zu ersetzende Text in der nächsten Zeile steht, ist der Befehl der Zeile ausreichend. Es kann auch erforderlich sein in Fällen, in denen der Text ersetzt werden soll, ist auch in der ursprünglichen Zeile vorhanden. Dies liegt daran, dass der Befehl multiline N die nächste Zeile in den Musterbereich zieht und die Ersetzung auf der kombinierten Zeile ausführt. Der Befehl Einzeilige nächste (n) wirkt nur auf die nächste Zeile. Dies wird unten veranschaulicht, wo N führt falsche Substitution:

$ cat class_prompt.php 
if (empty($donot_false_dump)) { 
       return false; 
$ sed '/if (empty(\$donot_false_dump)) {/{ N; s/false/true/ }' class_prompt.php 
if (empty($donot_true_dump)) { 
       return false; 
$ sed '/if (empty(\$donot_false_dump)) {/{ n; s/false/true/ }' class_prompt.php 
if (empty($donot_false_dump)) { 
       return true; 

Das mehrzeilige N notwendig ist, nur, wenn das Suchmuster mehrere Zeilen erstreckt.

Dies kann auch in Perl erfolgen.Wie unten

$ perl -pe 'if ($p) { s/false/true/ ; $p=0 } $p++ 
> if /if \(empty\(\$donot_false_dump \) \) {/ ' class_prompt.php 
if (empty($donot_false_dump)) { 
       return true; 
+1

Dies könnte einfach in einem Satz unter PesaThe's Antwort in einem Kommentar geschrieben werden. – ejmin

+0

Nein, konnte es nicht. Die Unterscheidung zwischen den beiden Befehlen wird am besten anhand eines Beispiels veranschaulicht. – SigmaPiEpsilon

+0

Aus dem Titel * Suche und Ersetze mehrere Zeilen *, habe ich geschlossen, dass mehrzeilige Änderungen in der Zukunft gewünscht werden, zum Beispiel Löschen. Deshalb habe ich 'N' und nicht' n' gewählt. Natürlich, wenn die Änderungen nur in einer Zeile nach einer bestimmten Regex gewünscht sind, ist 'n' genug. – PesaThe

0

Es sollte nicht mit sed erfolgen. sed ist für einfache Substitutionen auf einzelnen Zeilen, das ist alles. Wenn Sie etwas anderes damit machen, verwenden Sie Konstrukte, die in den 1980er Jahren obsolet wurden, als awk erfunden wurde und die normalerweise nicht portabel und ineffizient sind und nicht darauf gebaut werden können, etwas anderes zu tun.

diese Eingabedatei Gegeben:

$ cat file 
foo 
if (empty($donot_dump)) { 
       return false; 
bar 

die derzeit akzeptierte sed Antwort auf OSX Mit:

$ sed '/if (empty($donot_dump))/ { N; s/false/true/ }' file 
sed: 1: "/if (empty($donot_dum ...": bad flag in substitute command: '}' 

Mit jedem awk in jeder Schale auf jeder UNIX-Box:

$ awk 'f{sub(/false/,"true"); f=0} /if (empty($donot_dump))/{f=1} 1' file 
foo 
if (empty($donot_dump)) { 
       return false; 
bar 

aber in der Realität ist dieser ganze Ansatz fehleranfällig, da er einen Regexp anstelle von Stringvergleich und Doin verwendet g eine teilweise Übereinstimmung anstelle der vollständigen Übereinstimmung und funktioniert nur für die Übereinstimmung über 2 Zeilen. Wenn Sie an einer allgemeinen, robusten Lösung für diese Art von Aufgabe interessiert sind, dann veröffentlichen Sie eine neue Frage.

0

Überprüfen auf die erste if-Anweisung und wenn es gefunden wird, ersetzen Sie die nächste Zeile.

In Bezug auf die Substitutionsflags von Sed, g, ersetzen Sie alle Vorkommen.

$ sed 's/test/another test/g' myfile 

w flag: bedeutet schreiben Sie die Ergebnisse in eine Datei.

$ sed 's/test/another test/2' myfile 

nahm ich diese Beispiele aus dieser sed tutorial.

Verwandte Themen