ファイルから同じヘッダー行と列に対応する値を抽出するには?

ファイルから同じヘッダー行と列に対応する値を抽出するには?

次のファイルがあります

    1 2 3 4 5 
1   a b c d e
2   f g h i j
3   k l m n o
4   p k r s t
5   w x w z #

位置1,1 - 2,2 - 3,3 - 4,4と5,5に対応する値を抽出したいと思います。

つまり、希望の出力

1 2 3 4 5
a g m s # 

答え1

$ awk 'FNR == 1 { sub("^ *", ""); print; ORS=" "; next } { print $FNR } END { printf("\n") }' file
1 2 3 4 5
a g m s #

コードawkは次のことを行います。

  1. その行が最初の行の場合は、行の先頭のスペースを削除して印刷します。次に、出力レコード区切り文字(ORS)を空白に変更し、次の行に移動します。
  2. 他のすべての行については、行番号に対応するフィールドを印刷します。値のため、データは改行文字ではなく末尾のスペースで印刷されますORS
  3. 最後に改行文字が出力されます。

答え2

列または行がソートされていない場合、またはキーワードに依存している場合:

awk 'BEGIN {IFS=" +"} 
     NR==1 {for ( i=1 ; i<=NF ; i++ ) { ihead[$i]=i+1 }
     NR>1 { print $1,$ihead[$1] }' file

file
    5 2 1 4 3 
4   a b c d e
1   f g h i j
2   k l m n o
5   p k r s t
3   w x w z #

result
4 d
1 h
2 l
5 p
3 #

これをsortソート出力にパイプします。要件に合わせてフォーマットを調整するには、パイプdatamash -t' ' transpose(並べ替えられた出力用に事前実行sort)するか、より大きな方法で進めることができます。

awk 'BEGIN {IFS=" +"} 
     NR==1 {for ( i=1 ; i<=NF ; i++ ) { ihead[$i]=i+1 ; head[$i]=$i }
     NR>1 { result[$1]=$ihead[$1] }
     END { for (a in head) printf head[a]" "
           printf "\n"
           for (a in head) printf result[a]" "}' file

後者のawk場合()結果もソートされます(要素別、英数字順)。):

1 2 3 4 5 
h l # d p 

答え3

ファイルの列と行のインデックスは連続した数値なので、自然オフセットを使用できます。行インデックス --> 列インデックスへ:

$ awk 'NR == 1{ sub(/^ +/, ""); print; next }
      { sep= NR!=NF? FS:ORS; printf "%s%s", $NR, sep }' file
1 2 3 4 5
a g m s #

答え4

それとも

awk 'NR==1{print};NR>1 {printf $NR" "}' file | column -t

出力

1  2  3  4  5
a  g  m  s  #

column -t -o" "元の単一文字間隔が必要な場合は、次のようにします。

関連情報