Liebe alle, ich habe einegroßDatendatei sagen wir maldatei.datenthält es zwei Spalten
zB file.dat (zeigt wenige Zeilen)
0.0000 -23.4334
0.0289 -23.4760
0.0578 -23.5187
0.0867 -23.5616
0.1157 -23.6045
0.1446 -23.6473
0.1735 -23.6900
0.2024 -23.7324
0.2313 -23.7745
0.2602 -23.8162
0.2892 -23.8574
0.3181 -23.8980
0.3470 -23.9379
0.3759 -23.9772
0.4048 -24.0156
0.4337 -24.0532
0.4627 -24.0898
0.4916 -24.1254
note: data file has a blank line at the end of the file
Erwartete Ergebnisse
Ich möchte das Maximum und Minimum aus beiden Spalten finden/extrahieren, z. B. Spalte 1
max - 0.4916
min - 0.0000
ähnlich Spalte-2
max - -23.4334
min - -24.1254
Unvollständige Lösung (funktioniert nicht für Spalte 2)
Für Spalte-1
awk 'BEGIN{min=9}{for(i=1;i<=1;i++){min=(min<$i)?min:$i}print min;exit}' file.dat
0.0000
cat file.dat | awk '{if ($1 > max) max=$1}END{print max}'
0.4916
für Spalte-2
awk 'BEGIN{min=9}{for(i=2;i<=2;i++){min=(min<$i)?min:$i}print min;exit}' file.dat
-23.4334
cat file.dat | awk '{if ($2 > max) max=$2}END{print max}'
**no output showing**
Problem
Bitte helfen Sie mir, den Minimal- und Maximalwert aus Spalte 2 zu finden Hinweis: Die Datendatei hat am Ende eine Leerzeile.
Antwort1
Das Problem in Ihrem Code,
awk 'BEGIN{min=9}{for(i=2;i<=2;i++){min=(min<$i)?min:$i}print min;exit}' file.dat
... ist, dass Sie sofort exit
nach der Verarbeitung der ersten Zeile der Eingabe. Ihr mittlerer Block muss dort ausgelöst werden fürjedenZeile. Anschließend END
können Sie in einem Block die gefundenen Werte ausdrucken. Dies tun Sie in einem weiteren Codeausschnitt:
awk '{if ($1 > max) max=$1}END{print max}'
Ein weiteres Problem ist, dass Sie mit einer magischen Zahl initialisieren min
(9 im ersten Code, den ich zitiert habe, und 0 im zweiten Teil; Variablen, die nicht explizit initialisiert werden, haben den Wert 0, wenn Sie sie in Berechnungen verwenden). Wenn diese magische Zahl nicht in den Zahlenbereich der tatsächlichen Daten fällt, sind die berechneten Mindest- und/oder Höchstwerte falsch. Es ist besser, sowohl Mindest- als auch Höchstwerte auf einen in den Daten gefundenen Wert zu initialisieren.
VerfolgenbeideUm die Min- und Max-Werte zu ändern, benötigen Sie zwei Variablen und beide müssen zeilenweise mit den Daten in der Datei verglichen werden, um festzustellen, ob sie aktualisiert werden müssen.
Da awk
Arrays unterstützt werden, wäre es naheliegend, Arrays für min
und zu verwenden max
, mit einem Array-Element pro Spalte. Genau das habe ich im folgenden Code getan.
Verallgemeinert auf eine beliebige Anzahl von Spalten:
NF == 0 {
# Skip any line that does not have data
next
}
!initialized {
# Initialize the max and min for each column from the
# data on the first line of input that has data.
# Then immediately skip to next line.
nf = NF
for (i = 1; i <= nf; ++i)
max[i] = min[i] = $i
initialized = 1
next
}
{
# Loop over the columns to see if the max and/or min
# values need updating.
for (i = 1; i <= nf; ++i) {
if (max[i] < $i) max[i] = $i
if (min[i] > $i) min[i] = $i
}
}
END {
# Output max and min values for each column.
for (i = 1; i <= nf; ++i)
printf("Column %d: min=%s, max=%s\n", i, min[i], max[i])
}
Angesichts dieses Skripts und der Daten in der Frage:
$ awk -f script.awk file
Column 1: min=0.0000, max=0.4916
Column 2: min=-24.1254, max=-23.4334
Die Bedingung NF == 0
für den ersten Block (der für alle Zeilen ausgeführt wird) soll sicherstellen, dass wir leere Zeilen überspringen. Der Test bedeutet „wenn es in dieser Zeile null Felder (Spalten) mit Daten gibt“. Die Variable initialized
wird von Anfang an Null sein (logischFALSCH), sondern wird auf eins gesetzt (logischWAHR), sobald die erste Zeile mit Daten gelesen wurde.
Die nf
Variable wird in der Zeile, von der aus wir die und -Werte NF
initialisieren, auf (die Anzahl der Felder) initialisiert . Dies ist so, dass die Ausgabe im Block auch dann funktioniert, wenn die letzte Zeile null Felder hat.min
max
END
Antwort2
Eigentlich kann man alle Anweisungen in einem awk
Programm zusammenfassen:
awk 'NR==1{min1=max1=$1;min2=max2=$2}\
NR>1 {if ($1<min1) {min1=$1} else if ($1>max1) {max1=$1};\
if ($2<min2) {min2=$2} else if ($2>max2) {max2=$2}; }\
END{printf("Column1 min: %f\nColumn1 max: %f\nColumn2 min: %f\nColumn2 max:%f\n",min1,max1,min2,max2)}' file.dat
Dadurch werden die Minimal- und Maximalwerte für beide Spalten mit den jeweiligen Werten der ersten Zeile initialisiert (Regel mit Bedingung NR==1
) und anschließend werden die nachfolgenden Zeilen durchsucht, um zu sehen, ob die Werte jeweils größer als das aktuelle Maximum bzw. kleiner als das aktuelle Minimum sind (Regel mit Bedingung NR>1
).
Am Ende der Datei (Regel mit Bedingung END
) wird das Ergebnis ausgedruckt.
Beachtendass dies voraussetztEs gibt keine Leerzeilen. Wenn es welche gibt, müssen Sie die NR>1
Bedingung durch ersetzen NR>1 && NF>0
. Wenn es leere Zeilen geben kannvor dem ersten, verwenden
awk '!init && NF>0 {init=1; min1=max1=$1; min2=max2=$2} \
init==1 && NF>0 {if ($1<min1) {min1=$1} else if ($1>max1) {max1=$1};\
if ($2<min2) {min2=$2} else if ($2>max2) {max2=$2}; }\
END{printf("Column1 min: %f\nColumn1 max: %f\nColumn2 min: %f\nColumn2 max:%f\n",min1,max1,min2,max2)}' file.dat
Dabei wird mithilfe einer Variablen init
geprüft, ob bereits eine nicht leere Zeile gefunden wurde, und der Inhalt der ersten nicht leeren Zeile wird verwendet, um das aktuelle Maximum/Minimum für beide Spalten voreinzustellen. Nur wenn init
gesetzt ist (nach dieser Initialisierung), werden (nicht leere) Zeilen für die Eingabe dieser Statistik berücksichtigt.
Als allgemeine Bemerkung müssen Sie nie cat
eine Datei erstellen und das Ergebnis dorthin weiterleiten awk
.
Antwort3
Verwenden vondatamash
Und printf
:
for f in 1 2 ; do printf 'Column #%s\nmax - %s\nmin - %s\n\n' $f \
$(datamash -W max $f min $f < file.dat); done
...oder ohne Schleife:
printf 'Column #%s\nmax - %s\nmin - %s\n\n' \
$(datamash -W max 1 min 1 max 2 min 2 < file.dat |
tr -s '\t' '\n' | paste - - | nl)
Ausgabe von entweder:
Column #1
max - 0.4916
min - 0
Column #2
max - -23.4334
min - -24.1254
Antwort4
Dies für Spalte 1 (es berechnet den Durchschnitt, Maximum und Minimum)
sort -n -k 1 file |awk '{SUM+=$1 ; if ( NR == 1) MIN=$1} END{print "Average - "SUM/NR, "Min time - "MIN,"Max Time - "$1}'
dies für Spalte 2
sort -n -k 2 file |awk '{SUM+=$1 ; if ( NR == 1) MIN=$1} END{print "Average - "SUM/NR, "Min time - "MIN,"Max Time - "$1}'