次のファイルがあります
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
は次のことを行います。
- その行が最初の行の場合は、行の先頭のスペースを削除して印刷します。次に、出力レコード区切り文字(
ORS
)を空白に変更し、次の行に移動します。 - 他のすべての行については、行番号に対応するフィールドを印刷します。値のため、データは改行文字ではなく末尾のスペースで印刷されます
ORS
。 - 最後に改行文字が出力されます。
答え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" "
元の単一文字間隔が必要な場合は、次のようにします。