2017-03-07 2 views
2

Ausführen von Fedora 25 Server Edition. sed --version gibt mir sed (GNU sed) 4.2.2 zusammen mit den üblichen Copyright und Kontaktinformationen. Ich habe eine Textdatei sudo vi ./potential_sed_bug erstellt. Vi zeigt den Inhalt dieser Datei (mit :set list aktiviert) als:Warum löscht "sed -n -i" vorhandene Dateiinhalte?

don't$ 
delete$ 
me$ 
please$ 

ich dann führen Sie den folgenden Befehl ein:

sudo sed -n -i.bak /please/a\testing ./potential_sed_bug

Bevor wir diskutieren die Ergebnisse; hier ist das, was die sed man page sagt:

-n, --quiet, --silent Raum automatisches Drucken von Musterunterdrücken

und

-i [SUFFIX], - -in-place [= SUFFIX] Dateien an Ort und Stelle bearbeiten (macht Backup, wenn Erweiterung geliefert wird). Der Standardbetriebsmodus besteht darin, symbolische und harte Verbindungen zu unterbrechen. Dies kann mit --follow-symlinks und --copy geändert werden.

Ich habe auch other sed command references geschaut zu lernen, wie mit sed anhängen. Basierend auf meinem Verständnis aus der Forschung, die ich gemacht habe; der resultierende Datei-Inhalt sein sollte:

don't 
delete 
me 
please 
testing 

Allerdings läuft sudo cat ./potential_sed_bug gibt mir die folgende Ausgabe:

testing 

Im Lichte dieser Diskrepanz ist mein Verständnis des Befehls, den ich falsch lief, oder gibt es ein Fehler mit sed/der Umgebung?

Antwort

3

tl; dr

  • nicht -n mit -i Verwenden Sie: wenn Sie explizite Ausgabebefehle in Ihrem sed Skript verwenden, wird nichts auf Ihre Datei geschrieben werden.

  • -i Verwendung produziert keine stdout (Terminal) ausgegeben, so gibt es nichts extra Sie brauchen Ihren Befehl ruhig tun zu machen.


Standardmäßig druckt sed automatisch die (ggf. modifizierte) Eingangsleitungen, was auch immer seine Ausgabeziel ist, sei implizit oder explizit angegeben: In der Standardeinstellung zu stdout (das Endgerät, wenn nicht umgeleitet) ; mit -i, zu einer temporäre Datei, die letztlich die Eingabedatei ersetzt.

In beiden Fälle -nunterdrückt diesen automatischen Druck, so dass - wenn Sie explizite Ausgabe Funktionen wie p oder in Ihrem Fall, a-nichts zum temporären zu stdout/geschrieben gedruckt wird Datei.

  • beachten, dass der automatische Druck gilt für den sogenannten Musterraum, die ist, wo das (möglicherweise modifizierte) Eingang gehalten wird; explizite Ausgabefunktionen wie p, a, i und c tun nicht Druck des Musterraum (für mögliche spätere Änderung), sie drucken direkt mit dem Zielstrom/Datei, weshalb a\testing Lage Ausgabe zu erzeugen war, trotz der Verwendung von -n.

anzumerken, dass mit -i, sed ‚s impliziten Druck/explizite Ausgabe nur Druck in die temporäre Datei Befehle und auch nicht, in stdout so ein Befehl -i mit Bezug auf stdout immer ruhig ist (Terminal) Ausgabe - es gibt nichts extra, was Sie tun müssen.


Um ein konkretes Beispiel (GNUsed Syntax) zu geben.

Da die Verwendung von -i zu der Frage nebensächlich ist, habe ich es der Einfachheit halber weggelassen. Beachten Sie, dass -i zunächst auf eine temporäre Datei druckt, die nach Fertigstellung das Original durch ersetzt. Dies kommt mit Fallstricken, insbesondere die mögliche Zerstörung von Symlinks; siehe die untere Hälfte von this answer von mir.

# Print input (by default), and append literal 'testing' after 
# lines that contain 'please'. 
$ sed '/please/ a testing' <<<$'yes\nplease\nmore' 
yes 
please 
testing 
more 

# Adding `-n` suppresses the default printing, so only `testing` is printed. 
# Note that the sequence of processing is exactly the same as without `-n`: 
# If and when a line with 'please' is found, 'testing' is appended *at that time*. 
$ sed -n '/please/ a testing' <<<$'yes\nplease\nmore' 
testing 

# Adding an unconditional `p` (print) call undoes the effect of `-n`. 
$ sed -n 'p; /please/ a testing' <<<$'yes\nplease\nmore' 
yes 
please 
testing 
more 
+0

@AMemberofDollars: Die kurze davon: die Reihenfolge der Verarbeitung nicht ändert, und ja, wird die temporäre Datei zuerst geschrieben und erst nach Abschluss macht es das Original ersetzen - meinen Update finden Sie unter. – mklement0

+1

@stevesliva: Ich sehe, danke. Ich habe die Antwort entsprechend aktualisiert. – mklement0

+1

Was mich interessiert ist, dass ich immer 'sed -e cmd1 | sed -e cmd2' entspricht "sed -e cmd1 -e cmd2", aber dies ist ein Bereich, in dem Sie sed tatsächlich nach sed einfügen möchten, wenn Sie aus irgendeinem Grund einen Kontext hinzufügen, den Sie später ändern möchten. Ich denke, 'n' und' q' andere Befehle würden diese Äquivalenz ebenfalls brechen. – stevesliva

Verwandte Themen