Suchen Sie den Mindestwert in einer Spalte aus mehreren Dateien und drucken Sie ihn in einer anderen Datei aus.

Suchen Sie den Mindestwert in einer Spalte aus mehreren Dateien und drucken Sie ihn in einer anderen Datei aus.

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 sedVersion

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

sortdie 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' FILEwird 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 finddies 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_NEWda für jede gefundene Datei findblind alles weitere ausgeführt wird .-exec

verwandte Informationen