awk は列名に基づいてデータを印刷します。

awk は列名に基づいてデータを印刷します。

次のサポートが必要です

これは私の入力ファイルです。

cat sortcol
InfoId Time object Request1 Request2 Request3 Request4 Request5

次のawkスクリプトを使用して選択した列を印刷しています。

awk '
NR==1 {
for (i=1; i<=NF; i++) {
f[$i] = i
}
}
{ print $(f["InfoId"]), $(f["Time"]), $(f["object"]), $(f["Request1"]) , 
$(f["Request2"]) }
' sortcol | column -t
InfoId  Time  object  Request1  Request2

条件の設定方法に応じて、スクリプトはうまく機能します。この awk スクリプトで要求された列が入力ファイルにない場合は、その列を無視する必要があります。以下の例に示すように、ループが実行されているため、一致しない列名が見つかった場合は再実行され、入力ファイルのすべての列が印刷されます。

awk '
NR==1 {
for (i=1; i<=NF; i++) {
f[$i] = i
}
}
{ print $(f["InfoId"]), $(f["Time"]), $(f["object"]), $(f["Request1"]) ,$(f["Request2"]) , $(f["Request6"]) }
' sortcol | column -t
InfoId  Time  object  Request1  Request2  InfoId  Time  object  Request1  Request2  Request3  Request4  Request5

すべてのサポートに感謝します。

ベストアンサー1

〜のようにすでに気付いた$(f["field-name"])、コードの式は空の文字列として評価されるたびに、つまり入力ファイルの最初の行にないときに変換されます$0(したがって、行全体の内容に展開されます)。f["field-name"]field-name

別のAWKアプローチは次のとおりです。

BEGIN {
  nwanted = split(list,wanted,",")
}
NR == 1 {
  for ( iwanted = 1; iwanted <= nwanted; iwanted ++ )
    for ( ifield = 1; ifield <= NF; ifield++ )
      if ( wanted[iwanted] == $ifield )
        toprint[++ntoprint] = ifield
}
{
  for ( itoprint = 1; itoprint <= ntoprint; itoprint++ )
    printf( "%s%s", $toprint[itoprint], itoprint == ntoprint ? ORS : OFS )
}

次のように保存するとしますscript

awk -v list="InfoId,Time,object,..." -f script input_data

印刷する列名は変数としてlist渡されるため、awkスクリプトを編集せずに変更できます。

主なアイデアは、最初の行でtoprint行ヘッダーと変数を分割した配列()との交点に基づいて印刷するフィールド番号の配列()を生成することです。次に、各行の配列に番号が付いたフィールドを印刷します。wantedlist
to-print

空のリストをスクリプトに渡すか、リストに入力ファイルの最初の行にある値が含まれていない限り、何も印刷されません。

おすすめ記事