Presidents.txtというファイルがあります。内容は次のとおりです。
First Last Age Years
Geogre W 57 8.0
John A 61 4.0
Thomas J 57 8.0
James M 57 8.0
Andrew J 61 8.0
私に必要なのは、各大統領の年齢と研修を追加できるプログラムだ。たとえば、George Wは57+8.0、John Aは61+4.0などです。各大統領の番号を合計した後、プログラムは最も高い番号を持つ大統領の名前を出力します。たとえば、ここで出力は "Andrew J at 69"でなければなりません。これまでは、大統領ごとに一度に1つずつこれを実行できますが、awkループを使用して実行したいと思います。これまで私が使用したコマンドは次のとおりです。
awk 'NR==2 {print $3+$4}' presidents.txt
これは、数字61と4.0を追加して出力65を提供し、これが開始だと思います。ループと配列を使用する必要があると確信していますが、通常はUnixやコーディングの経験があまりないので、どこから始めるべきかわかりません。助けてくれてありがとう。
答え1
$ 3 + $ 4の重複結果がある場合は、入力からその結果の最後の出現のみを印刷したいとします。
$ cat tst.awk
NR>1 {
curYear = $3 + $4
if ( curYear >= maxYear ) {
maxName = $1 OFS $2
maxYear = curYear
}
}
END {
print maxName, "at", maxYear
}
$ awk -f tst.awk file
Andrew J at 69
たとえば、変更された入力ファイルの2人(Andrew J
およびSheila E
)すべての合計値が$ 3 + $ 4(69)の場合:
$ cat file
First Last Age Years
Geogre W 57 8.0
John A 61 4.0
Thomas J 57 8.0
James M 57 8.0
Andrew J 61 8.0
Sheila E 65 4.0
上記のスクリプトを使用して最終出力を取得します。
$ awk -f tst.awk file
Sheila E at 69
たぶんあなたは最初のものが欲しいかもしれません。
$ cat tst.awk
NR>1 {
curYear = $3 + $4
if ( curYear > maxYear ) {
maxName = $1 OFS $2
maxYear = curYear
}
}
END {
print maxName, "at", maxYear
}
$ awk -f tst.awk file
Andrew J at 69
またはすべて:
$ cat tst.awk
NR>1 {
curYear = $3 + $4
if ( curYear >= maxYear ) {
if ( curYear > maxYear ) {
numNames = 0
}
maxNames[++numNames] = $1 OFS $2
maxYear = curYear
}
}
END {
for ( nameNr=1; nameNr<=numNames; nameNr++ ) {
print maxNames[nameNr], "at", maxYear
}
}
$ awk -f tst.awk file
Andrew J at 69
Sheila E at 69
答え2
awk
次の組み合わせsort
:
awk '{print $1,$2,"at",$3+$4}' file | sort -k4nr | head -1
Andrew J at 69
年齢と年の合計を最後のフィールドとして中間ファイルを作成し、最後のフィールド、数字、および逆順をsort
使用して最後に最初の行のみを印刷します。k
4
n
r
head
これは、最大年が複数行の場合を処理するための改善です。私たちはそれらをすべて印刷します:
awk '{print $1,$2,"at",$3+$4}' file | sort -k4nr | uniq -f3 --group | sed '/^$/q'
uniq
重複行がグループ化され(最初のフィールドは無視、つまり最後の数字のみがテストされている)、3
f
グループを空の行に分割し、最初の空の行に最初のグループのみを印刷しますsed
。q
答え3
これを行うにはループや配列は必要ありません。努力する:
awk '
{ name= $1 OFS $2 OFS "at" OFS }
NR>1 { age=$3+$4 }
age>ageMax { ageMax=age; data=name; next }
age==ageMax { data= data ageMax ORS name }
END{ print data ageMax }' infile
{ name= $1 OFS $2 OFS "at" OFS }
将来の処理のために名前と姓を記録してください。ヘッダー行をスキップして「年」に「年齢」を追加します
NR>1{ age=$3+$4 }
。「age」の値が「ageMax」より大きい場合は、「ageMax」の値を「age」の値に更新し、「data」を「name」に更新します
age>ageMax { ageMax=age; data=name; next }
。このnext
文は、awkに残りのコード処理をスキップするように指示します。現在の行、awkは次の行を読み込みます。 1行が処理されます。同じ最大AgeMax値を見つけると、その値を「data」値に追加してすべての値を保持します
age==ageMax { data= data ageMax ORS name }
。すべてが必要でない場合は、コードのこの部分を削除すると、ageMaxが最も高い最初のレコードが返されるか、ageMaxが最も高い最後のレコードが返されることに置き換えられage>ageMax
ます。age>=ageMax
では
END{ print data ageMax }
結果を印刷します。