
Ich möchte alle Dateien im Verzeichnis durchlaufen.
Die Dateien sind wie folgt angeordnet:
<Overall>4
other data
<Overall>2
other data
......
Ich habe den Code:
for file in .dat;
do
awk 'x+=sub(/<Overall>/,""){y+=$0} END{print FILENAME, y/x}' $file
done
Dadurch wird der Durchschnitt der Werte in der Datei ausgedruckt. Ich möchte jedoch das Verzeichnis, in dem sich mein Skript befindet, als Argument nehmen und den awk-Befehl für alle .dat-Dateien im Verzeichnis ausführen.
Ich habe versucht, den Code zu verwenden:
for file in $1
aber bekomme den Fehler:
awk: cmd. line:1: fatal cannot open file `folder' for reading (No such file or directory)
Darüber hinaus möchte ich die Ausgabe der Durchschnittswerte von hoch nach niedrig sortieren können.
Antwort1
Zwei Varianten:
- Führen Sie eine Schleife über die Dateien aus und rufen Sie den Vorgang
awk
einmal für jede Datei auf, oder - Geben Sie dem
awk
Skript alle Dateien, lassen Sie es für jede Datei den Durchschnitt berechnen und im Verlauf einen Bericht erstellen.
Das Sortieren der Ergebnisse der folgenden Lösungen kann durch Weiterleiten der Ergebnisse über
sort -k2,2rn
Dadurch wird eine umgekehrte numerische Sortierung des zweiten Felds (der Durchschnittswerte) durchgeführt.
Erste Lösung:
#!/bin/sh
for name in "$1"/*.dat; do
test -f "$name" || continue # skip non-files
awk -F '>' '/<Overall>/ { s+=$NF; n++ } END { print FILENAME, s/n }' "$name"
done
Dieses Skript erwartet einen Verzeichnisnamen in der Befehlszeile als erstes und einziges Befehlszeilenargument. Das awk
Skript findet alle Zeilen, die die Zeichenfolge enthalten Overall
, und summiert (in s
) den Wert nach dem >
in dieser Zeile. Am Ende wird der Durchschnitt zusammen mit dem Dateinamen ausgegeben. Die Variable n
enthält die Anzahl, wie oft wir etwas zu hinzugefügt haben s
.
Zweite Lösung (erfordert GNU Awk):
#!/bin/sh
find "$1" -maxdepth 1 -type f -name '*.dat' \
-exec awk -F '>' '/<Overall>/ { s+=$NF; n++ } ENDFILE { print FILENAME, s/n; s=n=0 }' {} +
Dieses Skript erwartet wie das erste als einziges Befehlszeilenargument einen Verzeichnisnamen. Es dient find
dazu, ein awk
Skript mit so vielen .dat
Dateien wie möglich gleichzeitig auszuführen.
Das awk
Skript verwendet den ENDFILE
Trigger von GNU Awk, um die berechneten Werte auszugeben und die Variablen nach der Verarbeitung jeder Datei zurückzusetzen s
, n
bevor mit dem Lesen der nächsten Datei begonnen wird.
Dies könnte auch geschrieben worden sein als
#!/bin/sh
awk -F '>' '/<Overall>/ { s+=$NF; n++ } ENDFILE { print FILENAME, s/n; s=n=0 }' "$1"/*.dat
Dies setzt jedoch voraus, "$1"/*.dat
dass die Liste der Dateinamen nicht zu lang wird (dies erfordert außerdem, .dat
dass jeder Name eine reguläre Datei ist, was durch den obigen find
Befehl mit garantiert wird -type f
).