Ermittelt die Worthäufigkeit aller Wörter in einer Textdatei und sortiert die Druckausgabe

28

Ich hatte einen Befehl, der eine Textdatei durcharbeitete, alle Vorkommen der Wörter zählte und wie folgt ausdruckte:

user@box $˜ magic-command-i-forgot | with grep | and awk | sort ./textfile.txt
66: the
54: and
32: I
16: unix
12: bash
5:  internet
3:  sh
1: GNU/Linux

Es wird also nicht Zeile für Zeile, sondern Wort für Wort gesucht, und zwar für alle Wörter, nicht nur für 1 Wort. Ich hatte es vor langer Zeit irgendwo im Internet gefunden, aber ich kann es nicht finden oder mich daran erinnern.

Kusalananda
quelle

Antworten:

33

Ich würde transtelle von awk verwenden :

echo "Lorem ipsum dolor sit sit amet et cetera." | tr '[:space:]' '[\n*]' | grep -v "^\s*$" | sort | uniq -c | sort -bnr
  • tr Ersetzt nur Leerzeichen durch Zeilenumbrüche
  • grep -v "^\s*$" schneidet leere Zeilen aus
  • sort als Eingabe für uniq
  • uniq -c Vorkommen zählen
  • sort -bnr wird in umgekehrter numerischer Reihenfolge sortiert, wobei Leerzeichen ignoriert werden

Wow. Es stellte sich heraus, dass es ein großartiger Befehl war, Flüche pro Zeile zu zählen

finden . -name "* .py" -exec cat {} \; | tr '[: space:]' '[\ n *]' | grep -v "^ \ s * $" | sortieren | uniq -c | sort -bnr | grep fick

Seler
quelle
Kann verwendet werden tr -s, um mehrere Leerzeichen zu verarbeiten, insbesondere wenn Einrückungen auftreten.
Arcege
@Arcege: Guter Punkt. Obwohl es das Ergebnis nicht ändert, kann es das Skript ein wenig beschleunigen.
Seler
-g( --general-numeric-sort) Option sortkann in einigen Fällen vorzuziehen sein. ZB sort -nwird so bleiben 10\n1 4wie es ist, behandelt 1 4wie es ist 14, während sort -ges korrekt behandelt wird wie es ist 1 4\n10.
Skippy le Grand Gourou
netter Befehl, wirklich verdient eine Abstimmung :)
Noor
@seler Ich denke, Sie können den grep- und tr-Teil wie folgt noch einfacher gestalten: echo "Lorem ipsum dolor sit sit amet et cetera." | tr ' ' '\n' | grep -v "^$" | sort | uniq -c | sort -bnrBeachten Sie, dass ich ein Anfänger bin. Daher kann ich mich irren. Sie können uns gerne beraten.
smc
8
  1. Teilen Sie die Eingabe in Wörter auf, eines pro Zeile.
  2. Sortieren Sie die resultierende Liste der Wörter (Zeilen).
  3. Squash mehrere Vorkommen.
  4. Nach Vorkommensanzahl sortieren.

Um die Eingabe in Wörter aufzuteilen, ersetzen Sie jedes Zeichen, das Sie als Worttrennzeichen betrachten, durch eine neue Zeile.

<input_file \
tr -sc '[:alpha:]' '[\n*]' | # Add digits, -, ', ... if you consider
                             # them word constituents
sort |
uniq -c |
sort -nr
Gilles 'SO - hör auf böse zu sein'
quelle
Dies ist eine gute Antwort, da sie den Fall behandelt, in dem die Wörter direkt neben einer Nicht-Wort-Interpunktion stehen, die Sie ignorieren möchten.
David Grayson
5

Grep und awk werden nicht verwendet, aber dies scheint zu tun, was Sie wollen:

for w in `cat maxwell.txt`; do echo $w; done|sort|uniq -c
  2 a
  1 A
  1 an
  1 command
  1 considered
  1 domain-specific
  1 for
  1 interpreter,
  2 is
  1 language.
  1 line
  1 of
Bram
quelle
1
Dies funktioniert nicht, wenn die Eingabe Shell-Platzhalter enthält (die Sie hinzufügen müssen set -f) und die Interpunktion als Teil von Wörtern behandelt (was umständlich behoben werden kann, indem Interpunktionszeichen hinzugefügt werden IFS- viel Glück beim Versuch, Nicht-ASCII-Zeichensätze zu unterstützen). Dies ist bei sehr großen Eingabedateien nicht gut, da die gesamte Datei im Speicher abgelegt wird (dies sortist intelligenter).
Gilles 'SO- hör auf böse zu sein'
2

Ich glaube, du bist auf so etwas aus?

$ perl -n -e 'foreach ${k} (split(/\s+/)){++$h{$k}};END{foreach $l (keys(%h)){print "$h{$l}: ${l}\n"}}' /path/to/your/file | sort -n -k 1

natürlich kannst du das awkauch so machen :)

amitkr
quelle
2

Mit awk/sort/uniqlösung:

awk '{for(w=1;w<=NF;w++) print $w}' ~/textFile.txt | sort | uniq -c | sort -nr
Prinz John Wesley
quelle
Schön! Das hat einwandfrei funktioniert.
Stidmatt
0
file=/home/stefan/ooxml1.txt
for word in $(sed 's/[^A-Za-z]/ /g' $file | tr " " "\n" | sort -u)
do
  echo -n "$word "
  grep -c $word $file
done | sort -k2 -n 

Sortiert aufsteigend nach dem Teilen der Datei in Wörter.

Das einfache grep findet fishin fisheye, daher müssen Sie den grep-Befehl verbessern, um partielle Übereinstimmungen zu verhindern.

Dauert ungefähr 3 Sekunden für eine 25k-Textdatei auf einer Maschine im Zeitalter der klassischen Festplatte (IDE).

Für größere Dateien oder häufig ausgeführte Vorgänge ist ein Hash-Map-Ansatz besser, für einen selten ausgeführten Job oder kleinere Dateien jedoch möglicherweise ausreichend.

Benutzer unbekannt
quelle