Ich habe eine Datei1, die so aussieht
25 104.601 0.5
24.8488 104 0.5
24.5341 103 0.5
24.1844 102 0.5
24.1568 101 0.5
24.1568 100 0.5
24.1844 99 0.5
24.5341 98 0.5
Ich muss den Mindestwert aus Spalte 1 finden und ihn in einer anderen Datei ausdrucken_NEU
Jetzt muss ich das oben Gesagte für verschiedene Dateien wiederholen und das Minimum für mindestens 100 Dateien ermitteln.
Damit erhalte ich in file_NEW eine endgültige Ausgabe in etwa dieser
24.1568
23.3254 (from file2)
22.312 (from file3)
.....
Hier haben Datei2 und Datei3 ähnliche Datensätze wie Datei1. Alle Eingabedateien haben dieselben Namensmuster wie Datei*.txt und befinden sich im selben Verzeichnis
Kann jemand einen Vorschlag machen, wie das mit awk oder sed geht?
Danke
Antwort1
Um den Mindestwert zu finden, können wir den folgenden Befehl verwenden
Verwenden Sie den folgenden Befehl für jede Datei
awk 'NR==1{sum=$1}($1 < sum){sum=$1}END{print sum}' filename >> outputfile
Getestet und funktionierte einwandfrei
Antwort2
awk '{print $1 "\t(from " FILENAME ")"}' file* | sort -k1,1n | awk -F'\t' '!seen[$2]++'
Die oben genannten Funktionen funktionieren robust und effizient mit allen Ihren Eingabedateien gleichzeitig unter Verwendung von Standard-UNIX-Tools, z. B.:
$ cat file1
25 104.601 0.5
24.8488 104 0.5
24.5341 103 0.5
24.1844 102 0.5
24.1568 101 0.5
24.1568 100 0.5
24.1844 99 0.5
24.5341 98 0.5
$ cat file2
75 104.601 0.5
74.8488 104 0.5
74.5341 103 0.5
74.1844 102 0.5
74.1568 101 0.5
74.1568 100 0.5
74.1844 99 0.5
74.5341 98 0.5
$ awk '{print $1 "\t(from " FILENAME ")"}' file{1,2} | sort -k1,1n | awk -F'\t' '!seen[$2]++'
24.1568 (from file1)
74.1568 (from file2)
aber geht davon aus, dass keiner Ihrer Dateinamen Tabulatoren oder Zeilenumbruchzeichen enthält. Wenn sie Tabulatoren enthalten, können Sie sie mit einer einfachen Änderung behandeln:
awk '{print $1 "\t(from " FILENAME ")"}' file* |
sort -k1,1n |
awk '{f=$0; sub(/[^\t]*\t/,"",f)} !seen[f]++'
Wenn sie aber auch Zeilenumbrüche enthalten, benötigen Sie GNU-Tools, um \0
(NUL-)Terminatoren unterzubringen:
awk -v ORS='\0' '{print $1 "\t(from " FILENAME ")"}' file* |
sort -z -k1,1n |
awk -v RS='\0' '{f=$0; sub(/[^\t]*\t/,"",f)} !seen[f]++'
Antwort3
Eine sed
Version
find . -name "file*" -exec sh -c '
echo $(sort -nk1 "$1" | sed -n "1{s/ .*//p}" )" (from "${1##*/}")" ' sh {} \; | sort -nk1 > output.txt; cat output.txt
sort
die Ausgabedatei bei Bedarf zu bearbeiten und die Dateinamen hinzuzufügen
Antwort4
Wenn ich mich recht entsinne, möchten Sie dies für jede Datei:
awk 'NF' FILE | sort -n -k1 - | awk 'NR==1{print $1}' >> file_NEW
Das Initial awk 'NF' FILE
wird benötigt, falls Sie leere Leerzeilen in Eingabedateien haben. Sie haben nicht angegeben, ob Sie diesen Befehl rekursiv oder nicht rekursiv auf alle Dateien in einem bestimmten Verzeichnis oder nur auf einige Dateien mit bestimmten Mustern in ihren Namen ausführen möchten. Sie können find
dies jedoch folgendermaßen tun:
find . -name "FILE*" -exec sh -c 'awk "NF" FILE | sort -n -k1 - | awk "NR==1{print \$1}" >> file_NEW' sh {} \;
In diesem Fall wird der obige Befehl für alle Dateien im angegebenen Verzeichnis ausgeführt, deren Name mit beginnt FILE
.
Beachten Sie auch, dass die Ausgabe dadurch nicht unbedingt eine sortierte Liste ergibt, file_NEW
da für jede gefundene Datei find
blind alles weitere ausgeführt wird .-exec