Grundsätzlich möchte ich als Eingabetext aus einer Datei nehmen, eine Zeile aus dieser Datei entfernen und die Ausgabe an dieselbe Datei zurücksenden. Etwas in diese Richtung, wenn das klarer wird.
grep -v 'seg[0-9]\{1,\}\.[0-9]\{1\}' file_name > file_name
Wenn ich dies tue, erhalte ich jedoch eine leere Datei. Irgendwelche Gedanken?
Antworten:
Sie können dies nicht tun, da bash zuerst die Umleitungen verarbeitet und dann den Befehl ausführt. Wenn grep also auf Dateiname schaut, ist es bereits leer. Sie können jedoch eine temporäre Datei verwenden.
Ziehen Sie in Betracht
mktemp
, das tmpfile zu verwenden , beachten Sie jedoch, dass es sich nicht um POSIX handelt.quelle
>
wird die Datei durch die Umleitung geöffnet und abgeschnitten, bevor die Shell gestartet wirdgrep
.sponge
Befehl akzeptiert werden.Verwenden Sie für diese Art von Aufgaben einen Schwamm . Sein Teil von moreutils.
Versuchen Sie diesen Befehl:
quelle
brew install moreutils
.sudo apt-get install moreutils
auf Debian-basierten Systemen.Verwenden Sie stattdessen sed:
quelle
-i
ist nur eine Erweiterung von GNU.-i ''
dass die Erweiterung nicht unbedingt vorgeschrieben ist, die-i
Option jedoch einige Argumente erfordert .versuchen Sie dieses einfache
Ihre Datei wird diesmal nicht leer sein :) und Ihre Ausgabe wird auch auf Ihrem Terminal gedruckt.
quelle
/dev/null
oder ähnliche Stellen umleiten .Sie können den Umleitungsoperator (
>
oder>>
) nicht für dieselbe Datei verwenden, da dieser eine höhere Priorität hat und die Datei erstellt / abgeschnitten wird, bevor der Befehl überhaupt aufgerufen wird. Um zu vermeiden , dass, sollten Sie geeignete Tools wietee
,sponge
,sed -i
oder ein anderes Werkzeug , welche Ergebnisse in die Datei schreiben kann (zBsort file -o file
).Grundsätzlich ist es nicht sinnvoll, Eingaben in dieselbe Originaldatei umzuleiten, und Sie sollten dafür geeignete In-Place-Editoren verwenden, z. B. den Ex-Editor (Teil von Vim):
wo:
'+cmd'
/-c
- Führen Sie einen beliebigen Ex / Vim-Befehl ausg/pattern/d
- Entfernen Sie Linien, die einem Muster entsprechen, mit global (help :g
)-s
- stiller Modus (man ex
)-c wq
- ausführen:write
und:quit
BefehleSie können verwendet werden,
sed
das gleiche zu erreichen (wie bereits in anderen Antworten gezeigt), aber an Ort und Stelle (-i
) ist Nicht-Standard - FreeBSD - Erweiterung (unterschiedlich zwischen Unix / Linux arbeiten) und im Grunde ist es eine s tream ed itor, keine Datei - Editor . Siehe: Hat der Ex-Modus einen praktischen Nutzen?quelle
Eine Liner-Alternative - Legen Sie den Inhalt der Datei als Variable fest:
quelle
Da diese Frage das Top-Ergebnis in Suchmaschinen ist, ist hier ein Einzeiler basierend auf https://serverfault.com/a/547331 , der anstelle einer Subshell verwendet
sponge
(was häufig nicht Teil einer Vanilla-Installation wie OS X ist). ::Der allgemeine Fall ist:
Bearbeiten, die obige Lösung hat einige Einschränkungen:
printf '%s' <string>
sollte stattdessen verwendet werden,echo <string>
damit Dateien enthalten-n
, kein unerwünschtes Verhalten verursachen.x
an die Ausgabe anhängen und es außen durch Parametererweiterung einer temporären Variablen wie entfernen${v%x}
.$v
der Wert einer vorhandenen Variablen$v
in der aktuellen Shell-Umgebung gestampft. Daher sollten wir den gesamten Ausdruck in Klammern verschachteln, um den vorherigen Wert beizubehalten.null
aus der Ausgabe entfernt werden. Ich habe dies überprüft, indem ich es aufgerufendd if=/dev/zero bs=1 count=1 >> file_name
und hexadezimal mit angezeigt habecat file_name | xxd -p
. Istecho $(cat file_name) | xxd -p
aber ausgezogen. Daher sollte diese Antwort nicht für Binärdateien oder andere Dateien mit nicht druckbaren Zeichen verwendet werden, wie Lynch betonte .Die allgemeine Lösung (albiet etwas langsamer, speicherintensiver und immer noch nicht druckbare Zeichen entfernt) lautet:
Test von https://askubuntu.com/a/752451 :
Sollte drucken:
Während Sie
cat file_uniquely_named.txt > file_uniquely_named.txt
die aktuelle Shell aufrufen :Druckt eine leere Zeichenfolge.
Ich habe dies nicht an großen Dateien getestet (wahrscheinlich über 2 oder 4 GB).
Ich habe diese Antwort von Hart Simha und kos ausgeliehen .
quelle
cat
und es als erstes Argument an setztecho
. Natürlich werden nicht druckbare Variablen nicht richtig ausgegeben und die Daten werden beschädigt. Versuchen Sie nicht, eine Datei zurück zu sich selbst zu leiten, es kann einfach nicht gut sein.Es gibt auch
ed
(als Alternative zused -i
):quelle
Sie können dies durch Prozessersetzung tun .
Es ist allerdings ein bisschen
sleep
hackig, da Bash alle Pipes asynchron öffnet und wir das mit so YMMV umgehen müssen.In Ihrem Beispiel:
>(sleep 1 && cat > file_name)
Erstellt eine temporäre Datei, die die Ausgabe von grep empfängtsleep 1
Verzögerungen für eine Sekunde, um grep Zeit zum Parsen der Eingabedatei zu gebencat > file_name
schreibt schließlich die Ausgabequelle
Sie können Slurp mit POSIX Awk verwenden:
Beispiel
quelle
Versuche dies
quelle
Mit den folgenden Funktionen wird das Gleiche
sponge
erreicht, ohne dass dies erforderlich istmoreutils
:Der
--random-source=/dev/zero
Teil Tricksshuf
versucht, seine Sache zu erledigen, ohne überhaupt zu mischen, sodass er Ihre Eingabe puffert, ohne sie zu ändern.Es ist jedoch richtig, dass die Verwendung einer temporären Datei aus Leistungsgründen am besten ist. Hier ist eine Funktion, die ich geschrieben habe und die dies allgemein für Sie erledigt:
quelle
Dies ist sehr gut möglich. Sie müssen lediglich sicherstellen, dass Sie die Ausgabe zum Zeitpunkt des Schreibens in eine andere Datei schreiben. Dies kann erreicht werden, indem die Datei nach dem Öffnen eines Dateideskriptors entfernt wird, aber bevor Sie darauf schreiben:
Oder Zeile für Zeile, um es besser zu verstehen:
Es ist immer noch eine riskante Sache, denn wenn COMMAND nicht richtig ausgeführt wird, verlieren Sie den Dateiinhalt. Dies kann durch Wiederherstellen der Datei verringert werden, wenn COMMAND einen Exit-Code ungleich Null zurückgibt:
Wir können auch eine Shell-Funktion definieren, um die Verwendung zu vereinfachen:
Beispiel:
Beachten Sie außerdem, dass dadurch eine vollständige Kopie der Originaldatei erhalten bleibt (bis der dritte Dateideskriptor geschlossen wird). Wenn Sie Linux verwenden und die Datei, die Sie verarbeiten, zu groß ist, um zweimal auf die Festplatte zu passen, können Sie dieses Skript auschecken, mit dem die Datei blockweise an den angegebenen Befehl weitergeleitet wird, während die Zuordnung der bereits verarbeiteten Datei aufgehoben wird Blöcke. Lesen Sie wie immer die Warnungen auf der Verwendungsseite.
quelle
Normalerweise benutze ich dazu das Tee- Programm:
Es erstellt und entfernt selbst ein Tempfile.
quelle
tee
wird nicht garantiert, dass es funktioniert. Siehe askubuntu.com/a/752451/335781 .