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:
$ 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.