Einzigartige Sortierung: Leiten Sie die Ausgabe in dieselbe Datei um


14

Gibt es eine Möglichkeit, die Pipe-Ausgabe in derselben Datei zu speichern, in der sie verarbeitet wurde? Zum Beispiel ist es das, was ich gerade mache

$ cat filename | sort | uniq > result
$ rm -f filename
$ mv result filename

Ich habe mich gefragt, ob es eine Möglichkeit gibt, dies in nur einer Zeile zu tun (ohne diese Befehle mit && anzuhängen).

Dies ist nicht der Weg, sondern eine Idee zu bekommen

$ cat filename | sort | uniq > filename

2
echo $(cat filename | sort | uniq > result) > filenameoder so ? Ich komme gerade vorbei und habe keine Zeit, es zu versuchen.
MrVaykadji

Antworten:


18

Sie können spongeaus dem moreutils- Paket Folgendes verwenden :

LC_ALL=C sort -u filename | sponge filename

Sie brauchen auch keine Pipe nach uniq, da bei der Sortierung sortdie -uOption für eindeutige Zeilen besteht.

Beachten Sie, dass auf einem GNU-System mit UTF-8-Gebietsschemata sort -uoder sort | uniqnicht eindeutige Zeilen angegeben wurden, sondern die erste aus einer Folge von Zeilen, die in der aktuellen Ländereinstellung gleich sortiert sind.

$ printf '%b\n' '\U2460' '\U2461' | LC_ALL=en_US.utf8 sort | LC_ALL=en_US.utf8 uniq

gab dir nur . Wenn Sie das Gebietsschema in C ändern, wird die Sortierreihenfolge basierend auf den Bytewerten erzwungen:

$ export LC_ALL=C
$ printf '%b\n' '\U2460' '\U2461' | LC_ALL=C sort | LC_ALL=C uniq


12

Sie brauchen keinen zusätzlichen Befehl wie catund uniqund auch nicht rmBefehl und mvBefehl, um den Dateinamen zu entfernen und umzubenennen. benutze einfach den einfachen Befehl.

sort -u filename -o filename


 -u, --unique
        with -c, check for strict ordering; without -c, output only  the
        first of an equal run

 -o, --output=FILE
        write result to FILE instead of standard output

Wie es funktioniert?

sortDer Befehl sortiert Ihren Dateinamen und entfernt mit der -uOption doppelte Zeilen daraus. Dann -oschreibt mit der Option die Ausgabe in dieselbe Datei mit der In-Place-Methode.


3
Wenn das System während der sortAusführung abstürzt , verlieren Sie Ihre Originaldatei.
Cuonglm

@ Gnouc Also, das ist das Ende des Peches !! : '(
αғsнιη

1
Vielen Dank! in diesem beispiel mit ´ort´ sollte ich das besonders machen. Ich dachte jedoch über einen allgemeinen Fall nach. @ Gnouc, haha, es gibt keine Möglichkeit zu glauben, dass es dir nicht passiert ist, oder?
Whitenoisedb

3

Ihr vorgeschlagenes Beispiel (unten) funktioniert nicht, da Sie gleichzeitig aus derselben Datei lesen und in dieselbe Datei schreiben würden.

$ cat filename | sort | uniq > filename

Die Idee mit einer Pipe oder Umleitung ist, dass der Befehl auf der linken und rechten Seite jeder Pipe oder Umleitung gleichzeitig parallel ausgeführt wird. Der Befehl auf der rechten Seite verarbeitet Informationen so, wie sie ihm vom Befehl auf der linken Seite übergeben werden, während der Befehl auf der linken Seite noch ausgeführt wird.

Damit Ihr Szenario funktioniert, muss der Befehl, der aus der Datei liest, beendet werden, bevor der Befehl, der in die Datei schreibt, beginnt. Damit dies funktioniert, müssen Sie die Ausgabe zunächst an einen temporären Speicherort umleiten. Anschließend müssen Sie sie vom temporären Speicherort zurück in die Datei senden.

Ein besserer Weg, dies zu tun, ist im Grunde wie in Ihrem vorherigen Beispiel, in dem Sie zu einer temporären Datei umleiten und diese Datei dann wieder in das Original umbenennen (außer, dass Sie die Datei nicht zuerst löschen müssen, da das Verschieben alle vorhandenen Ziele löscht). .

$ cat filename | sort | uniq > result
$ mv -f result filename

Sie können es auch in einer Zeichenfolgenvariablen speichern. Dies funktioniert jedoch nur, wenn die Daten so klein sind, dass sie alle gleichzeitig in den Arbeitsspeicher passen.


Als jemand in einem empfohlenen bearbeiten löschte, können Sie ändern , cat filename | sortum nur sort filename- cathier nicht erforderlich ist.
Thomasrutter

Mein Beispiel unten war nicht der richtige Weg. Danke für die Klarstellung. catkönnte in diesem Fall unnötig sein, aber ich habe mich auf den Umleitungsteil konzentriert.
Whitenoisedb

1
Ich habe erklärt, warum Ihr Beispiel unten nicht funktioniert. Ich weiß, dass du wusstest, dass es nicht funktioniert hat.
Thomasrutter

Danke fürs klarstellen! Tatsächlich wusste ich nicht, was wirklich geschah.
Whitenoisedb

2

Sie können den teeBefehl verwenden:

sort -u filename | tee filename > /dev/null

Der teeBefehl liest von der Standardeingabe und schreibt in die Standardausgabe und -dateien.


2
Das funktioniert bei mir nicht.
Pjvandehaar

3
Dies funktioniert nicht askubuntu.com/a/752451
Steven Penny

Das funktioniert bei mir. zB, um eine Zeile an das Ende einer Datei zu verschieben: (cat ~/file | grep -v 3662 ; printentry 3662) | tee ~/file > /dev/nullfunktioniert. Wie der ursprüngliche Beitrag funktioniert dies nicht, wenn Sie nur > ~/fileohne die tee. Tee scheint hier ähnlich zu sein sort -o file, der in die genannte Datei schreibt, ohne dieselbe Pipe fortzusetzen.
Joshua Goldberg

Warten Sie, sorry! Ich habe empirisch gesehen, dass dies unvorhersehbar Daten verlieren wird, wie im Link von @Steven erläutert. Erstellen Sie eine Datei mit den Nummern 1..9 in 9 Zeilen. Folgendes wird mehrmals funktionieren und dann gelegentlich alle Daten aus der Datei entfernen: (cat x | grep -v 7 ; echo 7) | tee x > /dev/null; cat x Ich empfehle eine temporäre Datei und mvoder vielleicht die Lösung aus dem Link von @ Steven.
Joshua Goldberg

@ JoshuaGoldberg Hast du meine Antwort auf dieser Seite gesehen?
Steven Penny

0

Sie können Vim im Ex-Modus verwenden:

ex -sc 'sort u|x' filename
  1. sort u sortiere einzigartig

  2. x Schreiben Sie, wenn Änderungen vorgenommen wurden und beenden Sie das Programm

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.