Suchen Sie nach doppelten Zeilen in einer Datei und zählen Sie, wie oft jede Zeile dupliziert wurde.


529

Angenommen, ich habe eine Datei ähnlich der folgenden:

123 
123 
234 
234 
123 
345

Ich möchte herausfinden, wie oft '123' dupliziert wurde, wie oft '234' dupliziert wurde usw. Im Idealfall wäre die Ausgabe also wie folgt:

123  3 
234  2 
345  1

4
Welche Sprache möchten Sie verwenden?
VMAtm

Antworten:


791

Angenommen, es gibt eine Nummer pro Zeile:

sort <file> | uniq -c

Sie können das ausführlichere --countFlag auch mit der GNU-Version verwenden, z. B. unter Linux:

sort <file> | uniq --count

3
Dies ist, was ich mache, aber algorithmisch scheint dies nicht der effizienteste Ansatz zu sein (O (n log n) * avg_line_len, wobei n die Anzahl der Zeilen ist). Ich arbeite an Dateien, die mehrere Gigabyte groß sind, daher ist die Leistung ein zentrales Thema. Ich frage mich, ob es ein Tool gibt, das nur das Zählen in einem einzigen Durchgang unter Verwendung eines Präfixbaums (in meinem Fall haben Zeichenfolgen häufig gemeinsame Präfixe) oder ähnliches ausführt, das den Trick in O (n) * avg_line_len ausführen sollte. Kennt jemand ein solches Kommandozeilen-Tool?
Droggl

21
Ein zusätzlicher Schritt besteht darin, die Ausgabe davon in einen endgültigen 'sort -n'-Befehl zu leiten. Dadurch werden die Ergebnisse sortiert, nach denen Linien am häufigsten auftreten.
Samoz

79
Wenn Sie nur doppelte Zeilen drucken möchten, verwenden Sie 'uniq -d'
DmitrySandalov

6
Wenn Sie das Ergebnis erneut sortieren möchten, können Sie es sorterneut verwenden wie:sort <file> | uniq -c | sort -n
Abhishek Kashyap

413

Dadurch werden nur doppelte Zeilen mit folgenden Zählwerten gedruckt :

sort FILE | uniq -cd

oder mit langen GNU-Optionen (unter Linux):

sort FILE | uniq --count --repeated

Unter BSD und OSX müssen Sie grep verwenden , um eindeutige Zeilen herauszufiltern:

sort FILE | uniq -c | grep -v '^ *1 '

Für das gegebene Beispiel wäre das Ergebnis:

  3 123
  2 234

Wenn Sie die Anzahl aller Zeilen drucken möchten, einschließlich der Zeilen , die nur einmal angezeigt werden:

sort FILE | uniq -c

oder mit langen GNU-Optionen (unter Linux):

sort FILE | uniq --count

Für die angegebene Eingabe lautet die Ausgabe:

  3 123
  2 234
  1 345

Um die Ausgabe zu sortieren mit den häufigsten Zeilen oben , können Sie Folgendes tun (um alle Ergebnisse zu erhalten):

sort FILE | uniq -c | sort -nr

oder, um nur doppelte Zeilen zu erhalten, am häufigsten zuerst:

sort FILE | uniq -cd | sort -nr

Unter OSX und BSD wird der letzte:

sort FILE | uniq -c | grep -v '^ *1 ' | sort -nr

1
Guter Punkt mit der Option --repeated oder -d. So viel genauer als "| grep 2" oder ähnliches!
Lauri

Wie kann ich diesen Befehl ändern, um alle Zeilen abzurufen, deren Wiederholungszahl mehr als 100 beträgt?
Black_Rider

@Black_Rider Durch Hinzufügen von | sort -noder | sort -nrzur Pipe wird die Ausgabe nach Wiederholungsanzahl (aufsteigend bzw. absteigend) sortiert. Dies ist nicht das, was Sie fragen, aber ich dachte, es könnte helfen.
Andrea

1
@ Black_Rider awk scheint in der Lage zu sein, alle Arten von Berechnungen durchzuführen: in Ihrem Fall könnten Sie tun| awk '$1>100'
Andrea

4
@fionbio Sieht so aus, als könnten Sie -c und -d unter OSX uniq nicht zusammen verwenden . Vielen Dank für den Hinweis. Sie können grep verwenden, um eindeutige Zeilen herauszufiltern :sort FILE | uniq -c | grep -v '^ *1 '
Andrea

72

Um doppelte Zeilen in mehreren Dateien zu finden und zu zählen, können Sie den folgenden Befehl ausführen:

sort <files> | uniq -c | sort -nr

oder:

cat <files> | sort | uniq -c | sort -nr

30

Über ::

awk '{dups[$1]++} END{for (num in dups) {print num,dups[num]}}' data

Im awk 'dups[$1]++'Befehl enthält die Variable $1den gesamten Inhalt von Spalte1 und eckige Klammern sind Arrayzugriff. Daher wird für jede erste Spalte der Zeile in der dataDatei der Knoten des genannten Arrays dupsinkrementiert.

Und am Ende durchlaufen wir ein dupsArray mit numals Variable und drucken zuerst die gespeicherten Zahlen und dann die Anzahl der duplizierten Werte durch dups[num].

Beachten Sie, dass Ihre Eingabedatei am Ende einiger Zeilen Leerzeichen enthält. Wenn Sie diese löschen, können Sie sie $0anstelle des $1obigen Befehls verwenden :)


1
Ist das nicht ein bisschen übertrieben, wenn man bedenkt, dass wir es haben uniq?
Nathan Fellman

9
sort | uniqund die awk-Lösung hat ganz unterschiedliche Leistungs- und Ressourcenkompromisse: Wenn die Dateien groß und die Anzahl der verschiedenen Zeilen klein sind, ist die awk-Lösung viel effizienter. Die Anzahl der Zeilen ist linear, und die Raumnutzung ist in der Anzahl der verschiedenen Zeilen linear. OTOH, die awk-Lösung muss alle verschiedenen Zeilen im Speicher behalten, während (GNU) -Sortierung auf temporäre Dateien zurückgreifen kann.
Lars Noschinski

14

In Windows mit "Windows PowerShell" habe ich den unten genannten Befehl verwendet, um dies zu erreichen

Get-Content .\file.txt | Group-Object | Select Name, Count

Wir können auch das Cmdlet where-object verwenden, um das Ergebnis zu filtern

Get-Content .\file.txt | Group-Object | Where-Object { $_.Count -gt 1 } | Select Name, Count

Können Sie alle Vorkommen der Duplikate außer dem letzten löschen ... ohne die Sortierreihenfolge der Datei zu ändern?
JParram

6

Angenommen, Sie haben Zugriff auf eine Standard-Unix-Shell und / oder eine Cygwin-Umgebung:

tr -s ' ' '\n' < yourfile | sort | uniq -d -c
       ^--space char

Grundsätzlich gilt: Konvertieren Sie alle Leerzeichen in Zeilenumbrüche, sortieren Sie dann die übersetzte Ausgabe und geben Sie diese an uniq weiter und zählen Sie doppelte Zeilen.

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.