Frage Files unter Linux ändern (Schreiben in eine Datei auf einer Pipe)


Wie ändere ich eine Datei im Handumdrehen entlang einer Pipe?

Ich bin wahrscheinlich auf der Suche nach einer Möglichkeit, eine Datei am Anfang einer Pipe zu puffern, die im Gegensatz dazu:

    cat foo.txt | grep bar > foo.txt

... würde die Eingabedaten vor Zerstörung durch die Pipe selbst bewahren. Gibt es einen solchen Puffer auf Lager?


6
2018-06-24 11:13


Ursprung




Antworten:


Ich würde vermuten, dass sed immer noch die temporäre Datei erstellt, aber das folgende könnte tun, was Sie wollen? (Wenn Sie strace verwenden, zeigt dies möglicherweise an, ob sed eine temporäre Datei erstellt oder nicht).

sed -i '/bar/!d' foo.txt

Der Ausruf invertiert die Übereinstimmung, d ist für das Löschen, also entfernt dies alle Zeilen, die keinen Balken enthalten.


6
2018-06-24 11:31



Ja, das ist es, danke. - Alex


Versuche es mit dem Schwamm von mehr so was:

sed "s/root/toor/" /etc/passwd | grep -v joey | sponge /etc/passwd

Es sammelt die gesamte Eingabe, bevor es in die Ausgabe geschrieben wird.


12
2018-06-24 11:41



Ich wusste nie über Schwamm, das ist ein fantastisches Werkzeug, das ein lästiges Problem löst - Rory


Verwenden Sie >>, um den Inhalt zu erhalten.

cat foo.txt | grep bar >> foo.txt

Jetzt wird das an die Datei angehängt.

AFAIK, gibt es keine direkte Möglichkeit, Daten an eine Datei in der Shell voranzustellen. Wenn Sie vorausschalten möchten, müssen Sie möglicherweise eine temporäre Datei dazwischen verwenden.


1
2018-06-24 11:31





Abhängig davon, wie komplex Ihre Befehlszeile ist, können Sie die Laufleistung verlieren

cat foo.txt | grep bar | tee -a foo.txt

0
2018-06-24 11:41





Der beste Weg, dies zu tun, ist, sich daran zu erinnern, wie Dateien in Unix funktionieren - die Datei existiert, solange eine Verbindung zu der Datei besteht (Verzeichnis oder Prozess, der die Datei öffnet).

Öffnen Sie die Datei, löschen Sie diesen Verzeichniseintrag, und führen Sie dann den Prozess aus, der in einen neuen Verzeichniseintrag mit demselben Namen schreibt, der jedoch mit einem anderen Inode verknüpft ist.

Schließlich ist das Schöne daran, dass es für jede Art von Pipeline-Operation funktioniert, nicht nur für Dinge, die den temporären Dateipuffer-Hack ausführen können.

{ rm file ; sed -e s/this/that/g > file ; } < file

Ein Wort der Warnung - dies kann zu einer Katastrophe führen, wenn Sie Ihre Rewrite eine atomare Operation haben müssen. Unix bietet keine sauberen Möglichkeiten zum Sperren von Dateien, insbesondere nicht auf Shell-Ebene. Dies war ein Problem in den dunklen Zeiten, wenn Sie etwas wie das Bearbeiten einer Kennwortdatei auf einem ausgelasteten System, auf dem so etwas wie NIS ausgeführt wurde, taten. Jedes Mal, wenn mehr als ein Prozess in einer Datei liest / schreibt, seien Sie sehr vorsichtig, wenn Ihr System beschäftigt oder wichtig ist.

Die einzigen Operationen, die zu 100% atomar sind, sind Manipulationen der Verzeichniseinträge - rm / ln / mv (auf demselben Dateisystem).

So werden die Dinge jetzt länger und hässlicher.

Der mathematische Teil erfordert eine Posix-Shell oder eine ähnlich erweiterte Bourne-Shell

c=0
    while
      f=$SECONDS
      test -f file.$c.tmp
    do
      c=$(($c+1))
    done

  grep stuff < file > file.$c.tmp && mv file.$c.tmp file

0
2018-06-24 13:07





Hoppla, UUOC, nutzloser Gebrauch der Katze :) Du brauchst keine Katze da:

grep something somefile > someotherfile

Wie Sekenre sagte, gibt es Schwamm. Oder vielleicht möchten Sie Perl Inline-Edition versuchen (-i Schalter):

  • Nur passende Ausgabe ausgeben:

    perl -ni -e 'm / foo / g und drucken' bar.txt

  • Ersetzen Sie "foo" durch "bar" in der Datei:

    Perl -pi -e 's / foo / bar / g' bar.txt


0
2018-06-24 14:26