GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Verwenden Sie awk, um die Buchstabenhäufigkeit zu berechnen

Ich habe vor kurzem angefangen, ein Spiel zu schreiben, bei dem Sie Wörter aus Buchstabenplättchen bilden. Um das Spiel zu erstellen, musste ich die Häufigkeit von Buchstaben in normalen Wörtern in der englischen Sprache kennen, damit ich einen nützlichen Satz von Buchstabenkacheln präsentieren konnte. Die Buchstabenhäufigkeit wird an verschiedenen Stellen diskutiert, auch auf Wikipedia, aber ich wollte die Buchstabenhäufigkeit selbst berechnen.

Linux bietet eine Liste von Wörtern in /usr/share/dict/words Datei, also habe ich bereits eine Liste mit wahrscheinlich zu verwendenden Wörtern. Die words Datei enthält viele Wörter, die ich will, aber ein paar, die ich nicht will. Ich wollte eine Liste aller Wörter, die keine zusammengesetzten Wörter (keine Bindestriche oder Leerzeichen) oder Eigennamen (keine Großbuchstaben) sind. Um diese Liste zu erhalten, kann ich grep ausführen Befehl, nur die Zeilen herauszuziehen, die nur aus Kleinbuchstaben bestehen:

$ grep  '^[a-z]*$' /usr/share/dict/words

Dieser reguläre Ausdruck fragt nach grep um Muster abzugleichen, die nur aus Kleinbuchstaben bestehen. Die Zeichen ^ und $ im Muster stellen jeweils den Anfang und das Ende der Linie dar. Der [a-z] Die Gruppierung entspricht nur den Kleinbuchstaben a bis z .

Hier ist ein kurzes Beispiel für die Ausgabe:

$ grep  '^[a-z]*$' /usr/share/dict/words | head
a
aa
aaa
aah
aahed
aahing
aahs
aal
aalii
aaliis

Weitere Linux-Ressourcen

  • Spickzettel für Linux-Befehle
  • Spickzettel für fortgeschrittene Linux-Befehle
  • Kostenloser Online-Kurs:RHEL Technical Overview
  • Spickzettel für Linux-Netzwerke
  • SELinux-Spickzettel
  • Spickzettel für allgemeine Linux-Befehle
  • Was sind Linux-Container?
  • Unsere neuesten Linux-Artikel

Und ja, das sind alles gültige Worte. Zum Beispiel ist „aahed“ der Ausruf der Vergangenheitsform von „aah“, wie in Entspannung. Und ein "Aalii" ist ein buschiger tropischer Strauch.

Jetzt muss ich nur noch einen gawk schreiben Skript, um die Buchstaben in jedem Wort zu zählen und dann die relative Häufigkeit jedes gefundenen Buchstabens auszugeben.

Buchstaben zählen

Eine Möglichkeit, Buchstaben in gawk zu zählen besteht darin, jedes Zeichen in jeder Eingabezeile zu durchlaufen und die Vorkommen jedes Buchstabens a zu zählen bis z . Der substr Die Funktion gibt eine Teilzeichenfolge einer bestimmten Länge, z. B. einen einzelnen Buchstaben, aus einer größeren Zeichenfolge zurück. Dieses Codebeispiel wertet beispielsweise jedes Zeichen c aus aus der Eingabe:

{
    len = length($0); for (i = 1; i <= len; i++) {
        c = substr($0, i, 1);
    }
}

Wenn ich mit einem globalen String LETTERS beginne das das Alphabet enthält, kann ich den index verwenden Funktion, um die Position eines einzelnen Buchstabens im Alphabet zu finden. Ich erweitere das gawk Codebeispiel, um nur die Buchstaben a auszuwerten bis z in der Eingabe:

BEGIN { LETTERS = "abcdefghijklmnopqrstuvwxyz" }
 
{
    len = length($0); for (i = 1; i <= len; i++) {
        c = substr($0, i, 1);
        ltr = index(LETTERS, c);
    }
}

Beachten Sie, dass die Indexfunktion das erste Vorkommen des Buchstabens aus LETTERS zurückgibt Zeichenfolge, beginnend mit 1 beim ersten Buchstaben oder Null, wenn nicht gefunden. Wenn ich ein Array habe, das 26 Elemente lang ist, kann ich das Array verwenden, um die Vorkommen jedes Buchstabens zu zählen. Ich füge dies zu meinem Codebeispiel hinzu, um es zu inkrementieren (mit ++ ) die Anzahl für jeden Buchstaben, wie er in der Eingabe erscheint:

BEGIN { LETTERS = "abcdefghijklmnopqrstuvwxyz" }
 
{
    len = length($0); for (i = 1; i <= len; i++) {
        c = substr($0, i, 1);
        ltr = index(LETTERS, c);
 
        if (ltr > 0) {
            ++count[ltr];
        }
    }
}

Drucken der relativen Häufigkeit

Nach dem gawk Skript alle Buchstaben zählt, möchte ich die Häufigkeit jedes gefundenen Buchstabens drucken. Mich interessiert nicht die Gesamtzahl jedes Buchstabens aus der Eingabe, sondern die relative Häufigkeit jedes Buchstabens. Die relative Häufigkeit skaliert die Anzahl so, dass der Buchstabe mit den wenigsten Vorkommen (z. B. der Buchstabe q ) ist auf 1 gesetzt, und andere Buchstaben sind relativ dazu.

Ich beginne mit der Zählung für den Buchstaben a , dann vergleichen Sie diesen Wert mit den Zählungen für jeden der anderen Buchstaben b bis z :

END {
    min = count[1]; for (ltr = 2; ltr <= 26; ltr++) {
        if (count[ltr] < min) {
            min = count[ltr];
        }
    }
}

Am Ende dieser Schleife wird die Variable min enthält die Mindestanzahl für jeden Buchstaben. Ich kann das verwenden, um eine Skala für die Anzahl bereitzustellen, um die relative Häufigkeit jedes Buchstabens auszudrucken. Zum Beispiel, wenn der Buchstabe mit dem niedrigsten Vorkommen q ist , dann min wird gleich dem q sein zählen.

Dann schleife ich jeden Buchstaben durch und drucke ihn mit seiner relativen Häufigkeit. Ich teile jede Zählung durch min um die relative Häufigkeit zu drucken, was bedeutet, dass der Buchstabe mit der niedrigsten Zahl mit einer relativen Häufigkeit von 1 gedruckt wird. Wenn ein anderer Buchstabe doppelt so oft vorkommt wie die niedrigste Zahl, hat dieser Buchstabe eine relative Häufigkeit von 2. Nur ich Ich interessiere mich hier für ganzzahlige Werte, also sind 2,1 und 2,9 für meine Zwecke dasselbe wie 2:

END {
    min = count[1]; for (ltr = 2; ltr <= 26; ltr++) {
        if (count[ltr] < min) {
            min = count[ltr];
        }
    }
 
    for (ltr = 1; ltr <= 26; ltr++) {
        print substr(LETTERS, ltr, 1), int(count[ltr] / min);
    }
}

Alles zusammenfügen

Jetzt habe ich einen gawk Skript, das die relative Häufigkeit von Buchstaben in seiner Eingabe zählen kann:

#!/usr/bin/gawk -f
 
# only count a-z, ignore A-Z and any other characters
 
BEGIN { LETTERS = "abcdefghijklmnopqrstuvwxyz" }
 
{
    len = length($0); for (i = 1; i <= len; i++) {
        c = substr($0, i, 1);
        ltr = index(LETTERS, c);
 
        if (ltr > 0) {
            ++count[ltr];
        }
    }
}
 
# print relative frequency of each letter
   
END {
    min = count[1]; for (ltr = 2; ltr <= 26; ltr++) {
        if (count[ltr] < min) {
            min = count[ltr];
        }
    }
 
    for (ltr = 1; ltr <= 26; ltr++) {
        print substr(LETTERS, ltr, 1), int(count[ltr] / min);
    }
}

Ich speichere das in einer Datei namens letter-freq.awk damit ich es einfacher über die Befehlszeile verwenden kann.

Wenn Sie möchten, können Sie auch chmod +x verwenden um die Datei selbst ausführbar zu machen. Der #!/usr/bin/gawk -f in der ersten Zeile bedeutet, dass Linux es als Skript mit /usr/bin/gawk ausführt Programm. Und weil der gawk Befehlszeile verwendet -f Um anzugeben, welche Datei als Skript verwendet werden soll, benötigen Sie das hängende -f damit letter-freq.awk ausgeführt wird in der Shell wird richtig interpretiert als /usr/bin/gawk -f letter-freq.awk ausgeführt wird stattdessen.

Ich kann das Skript mit ein paar einfachen Eingaben testen. Zum Beispiel, wenn ich das Alphabet in mein gawk einfüge sollte jeder Buchstabe eine relative Häufigkeit von 1:

haben
$ echo abcdefghijklmnopqrstuvwxyz | gawk -f letter-freq.awk
a 1
b 1
c 1
d 1
e 1
f 1
g 1
h 1
i 1
j 1
k 1
l 1
m 1
n 1
o 1
p 1
q 1
r 1
s 1
t 1
u 1
v 1
w 1
x 1
y 1
z 1

Wiederholen Sie dieses Beispiel, aber fügen Sie eine zusätzliche Instanz des Buchstabens e hinzu druckt den Buchstaben e mit einer relativen Häufigkeit von 2 und jedem zweiten Buchstaben als 1:

$ echo abcdeefghijklmnopqrstuvwxyz | gawk -f letter-freq.awk
a 1
b 1
c 1
d 1
e 2
f 1
g 1
h 1
i 1
j 1
k 1
l 1
m 1
n 1
o 1
p 1
q 1
r 1
s 1
t 1
u 1
v 1
w 1
x 1
y 1
z 1

Und jetzt kann ich den großen Schritt machen! Ich verwende den grep Befehl mit dem /usr/share/dict/words Datei und ermitteln Sie die Buchstabenhäufigkeit für alle Wörter, die vollständig in Kleinbuchstaben geschrieben sind:

$ grep  '^[a-z]*$' /usr/share/dict/words | gawk -f letter-freq.awk
a 53
b 12
c 28
d 21
e 72
f 7
g 15
h 17
i 58
j 1
k 5
l 36
m 19
n 47
o 47
p 21
q 1
r 46
s 48
t 44
u 25
v 6
w 4
x 1
y 13
z 2

Von allen Kleinbuchstaben in /usr/share/dict/words Datei, die Buchstaben j , q , und x am wenigsten häufig vorkommen. Der Buchstabe z ist auch ziemlich selten. Nicht überraschend, der Buchstabe e wird am häufigsten verwendet.


Linux
  1. So verwenden Sie den Su-Befehl unter Linux

  2. Eine Anleitung für Anfänger zum gawk

  3. Wie verwendet man Awk, um nur Zeilen mit 5 Spalten zu drucken?

  4. Verwenden von grep vs. awk

  5. Kann den Userspace-Cpufreq-Governor nicht verwenden und die CPU-Frequenz einstellen

Warum ich rxvt als Terminal verwende

Awk-Befehl unter Linux

Verwenden Sie den vi-Editor

So verwenden Sie Instagram im Terminal

So verwenden Sie den PS-Befehl

So verwenden Sie den TOP-Befehl