awkは他の列にその行を追加します。

awkは他の列にその行を追加します。

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使用して最後に最初の行のみを印刷します。k4nrhead


これは、最大年が複数行の場合を処理するための改善です。私たちはそれらをすべて印刷します:

awk '{print $1,$2,"at",$3+$4}' file | sort -k4nr | uniq -f3 --group | sed '/^$/q'

uniq重複行がグループ化され(最初のフィールドは無視、つまり最後の数字のみがテストされている)、3 fグループを空の行に分割し、最初の空の行に最初のグループのみを印刷しますsedq

答え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 }結果を印刷します。

関連情報