
Ich habe eine Datei mit vielen Zahlen (nur Zahlen und jede Zahl steht in einer Zeile). Ich möchte die Anzahl der Zeilen herausfinden, in denen die Zahl größer als 100 ist (oder tatsächlich irgendetwas anderes). Wie kann ich das tun?
Antwort1
Betrachten wir diese Testdatei:
$ cat myfile
98
99
100
101
102
103
104
105
Zählen wir nun die Anzahl der Zeilen mit einer Zahl größer als 100:
$ awk '$1>100{c++} END{print c+0}' myfile
5
Wie es funktioniert
$1>100{c++}
Jedes Mal, wenn die Zahl in der Zeile größer als 100 ist,
c
wird die Variable um 1 erhöht.END{print c+0}
Nachdem wir mit dem Lesen der Datei fertig sind,
c
wird die Variable ausgedruckt.Indem wir zu hinzufügen
0
,c
zwingen wir awk, esc
wie eine Zahl zu behandeln. Wenn es Zeilen mit Zahlen gäbe>100
, dannc
ist bereits eine Zahl. Wenn nicht, dannc
wäre ein leeres (Hut ab:iruvar). Indem wir eine Null hinzufügen, ändern wir die leere Zeichenfolge in ein0
, wodurch eine korrektere Ausgabe entsteht.
Antwort2
Ähnliche Lösung mitperl
$ seq 98 105 | perl -ne '$c++ if $_ > 100; END{print $c+0 ."\n"}'
5
Geschwindigkeitsvergleich:Zahlen für 3 aufeinanderfolgende Durchläufe gemeldet
Zufällige Datei:
$ perl -le 'print int(rand(200)) foreach (0..10000000)' > rand_numbers.txt
$ perl -le 'print int(rand(100200)) foreach (0..10000000)' >> rand_numbers.txt
$ shuf rand_numbers.txt -o rand_numbers.txt
$ tail -5 rand_numbers.txt
114
100
66125
84281
144
$ wc rand_numbers.txt
20000002 20000002 93413515 rand_numbers.txt
$ du -h rand_numbers.txt
90M rand_numbers.txt
Mitawk
$ time awk '$1>100{c++} END{print c+0}' rand_numbers.txt
14940305
real 0m7.754s
real 0m8.150s
real 0m7.439s
Mitperl
$ time perl -ne '$c++ if $_ > 100; END{print $c+0 ."\n"}' rand_numbers.txt
14940305
real 0m4.145s
real 0m4.146s
real 0m4.196s
Und nur zum Spaß mit grep
(Aktualisiert: sogar schneller als Perl mit LC_ALL=C)
$ time grep -xcE '10[1-9]|1[1-9][0-9]|[2-9][0-9]{2,}|1[0-9]{3,}' rand_numbers.txt
14940305
real 0m10.622s
$ time LC_ALL=C grep -xcE '10[1-9]|1[1-9][0-9]|[2-9][0-9]{2,}|1[0-9]{3,}' rand_numbers.txt
14940305
real 0m0.886s
real 0m0.889s
real 0m0.892s
sed
macht keinen Spaß:
$ time sed -nE '/^10[1-9]|1[1-9][0-9]|[2-9][0-9]{2,}|1[0-9]{3,}$/p' rand_numbers.txt | wc -l
14940305
real 0m11.929s
$ time LC_ALL=C sed -nE '/^10[1-9]|1[1-9][0-9]|[2-9][0-9]{2,}|1[0-9]{3,}$/p' rand_numbers.txt | wc -l
14940305
real 0m6.238s