Ich habe gerade Folgendes in bash ausgeführt:
uniq .bash_history > .bash_history
und meine Verlaufsdatei endete völlig leer.
Ich denke, ich brauche eine Möglichkeit, die gesamte Datei zu lesen, bevor ich darauf schreibe. Wie geht das?
PS: Ich habe natürlich darüber nachgedacht, eine temporäre Datei zu verwenden, aber ich suche nach einer eleganteren Lösung.
bash
Wenn Sie HISTCONTROL so einstellen, dass ignorierte Ups eingeschlossen werden , werden keine aufeinanderfolgenden Dupes in den Verlauf aufgenommen. Siehe die Manpage.Antworten:
Ich empfehle die Verwendung
sponge
von moreutils . Aus der Manpage:Um dies auf Ihr Problem anzuwenden, versuchen Sie:
quelle
Ich wollte nur eine andere Antwort beisteuern, die einfach ist und keinen Schwamm verwendet (da sie in leichten Umgebungen oft nicht enthalten ist).
sollte das gewünschte Ergebnis haben. Die Subshell wird ausgeführt, bevor .bash_history zum Schreiben geöffnet wird. Wie in der Antwort von Phil P erläutert, wurde .bash_history im Originalbefehl bereits vom Operator '>' abgeschnitten.
quelle
$()
wegen einiger Probleme eine Subshell anstelle von Backticks verwenden.echo "$(fmt -p '# ' -w 50 readme.txt)" > readme.txt
heute benutzt. Ich habe lange nach einer eleganten Lösung gesucht. Vielen Dank, @Hart Simha!Das Problem ist, dass Ihre Shell die Befehlspipeline einrichtet, bevor Sie die Befehle ausführen. Es geht nicht um "Ein- und Ausgabe", sondern darum, dass der Inhalt der Datei bereits gelöscht ist, bevor uniq überhaupt ausgeführt wird. Es geht so etwas wie:
>
Ausgabedatei zum Schreiben und schneidet sie abEs gibt verschiedene Lösungen, einschließlich der In-Place-Bearbeitung und der Verwendung temporärer Dateien, die von anderen erwähnt werden. Der Schlüssel ist jedoch, das Problem zu verstehen, was tatsächlich schief geht und warum.
quelle
Ein weiterer Trick, der ohne Verwendung von ausgeführt werden kann
sponge
, ist der folgende Befehl:Dies ist einer der Cheats, die im hervorragenden Artikel "In-Place" -Bearbeitung von Dateien auf backreference.org beschrieben sind.
Es öffnet im Grunde die Datei zum Lesen und "entfernt" sie dann. Es wird jedoch nicht wirklich entfernt: Es gibt einen offenen Dateideskriptor, der darauf verweist, und solange dieser offen bleibt, ist die Datei noch vorhanden. Dann erstellt es eine neue Datei mit demselben Namen und schreibt die eindeutigen Zeilen hinein.
Nachteil dieser Lösung: Wenn
uniq
aus irgendeinem Grund ein Fehler auftritt, ist Ihr Verlauf nicht mehr vorhanden.quelle
Verwenden Sie einen Schwamm von moreutils
quelle
Dieses
sed
Skript entfernt benachbarte Duplikate. Mit dieser-i
Option wird die Änderung direkt vorgenommen. Es ist aus dersed
info
Datei:quelle
strace
Illustration hinzu (nicht, dass es wirklich wichtig ist) :-)process input > tmp && mv tmp input
viel einfacher und lesbarer ist als das Verwenden vonsed
Tricks, nur um eine temporäre Datei zu vermeiden, und mein Original wird nicht überschrieben, wenn es fehlschlägt (ich weiß nicht, obsed -i
es ordnungsgemäß fehlschlägt - ich würde es tun) denke, es würde aber). Außerdem gibt es eine Menge Dinge, die Sie mit der Ausgabe-in-Temp-Datei-Methode tun können, die nicht ohne etwas noch Komplizierteres als diesessed
Skript an Ort und Stelle durchgeführt werden können. Ich weiß, dass Sie das alles wissen, aber es kann einigen Zuschauern nützen.Als interessanten Leckerbissen verwendet sed auch eine temporäre Datei (dies erledigt es nur für Sie):
Beschreibung:
Die Datei tempfile
./sedPmPv9z
wird zu fd 4 und diefoo
Dateien werden zu fd 3. Die Leseoperationen werden auf fd 3 ausgeführt und die Schreiboperationen auf fd 4 (die temporäre Datei). Die foo-Datei wird dann beim Umbenennungsaufruf mit der temporären Datei überschrieben.quelle
Eine andere Lösung:
quelle
Eine temporäre Datei ist so ziemlich alles, es sei denn, der betreffende Befehl unterstützt die direkte Bearbeitung (
uniq
nicht - manchesed
tun dies (sed -i
)).quelle
Sie können Vim im Ex-Modus verwenden:
%
Wählen Sie alle Zeilen aus!
Führen Sie den Befehl ausx
speichern und schließenquelle
Sie können auch tee verwenden und die Ausgabe von uniq als Eingabe verwenden:
quelle