ファイルからデータを抽出し、大きな固定幅テーブルで構成したいと思います。テーブルには複数の列があると予想されます。 30列があるとしましょう。このテーブルを作成するために既存のコマンドラインを使用した場合は、次のような非常にawk
長いコマンドラインを作成する必要があります。awk
awk '{printf "%-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s %-5s\n", $1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30}'
この線形を短くする方法はありますか?たとえば、上記の長いコマンドで配列を実装したいとします。配列は、awk
次のように各列を個別に定義するのではなく、作成する列の数と幅を示します。
awk 'BEGIN {for i in {1..30}; do echo %-5s\n print i}
awk
複数の固定幅列を生成するためにこの方法を内部的に正しく実装するにはどうすればよいですか?
答え1
一度に1フィールドずつループ内で印刷自体を実行できます。
awk '{for(i=1;i<=NF;i++) { printf "%-5s",$i } ; printf("\n"); }'
複数行が1つにマージされるのを防ぐには、ループの後に改行文字を印刷する必要があります。
例えば
echo a b c 32 87 x5 | awk '{for(i=1;i<=NF;i++) { printf "%-5s",$i } ; printf("\n"); }'
a b c 32 87 x5
答え2
段階的にいくつかの変数を構築できますが、お勧めしません(bashの例)。
$ printf -v l '%s ' {1..30} # list of numbers to use
$ printf -v a '%.0s%%-5s ' $l # make a string of repeated "%-5s"
$ printf -v b ',$%s' $l # make string of field numbers as "$1,$2.."
$ awk -va="$a" '{printf a "\n"'"$b"'}' infile4
しかし、awkでもこれをすべて行うことができます。
$ awk '{split($0,a); for(i in a){printf "%-5s", $i}; print ""}' infile
- inは、行をフィールドに分割し、各値を配列に入れるのに使用したのと
split
同じawk
正規表現を使用します。FS
a
for
すべてのフィールドを(自動的に)繰り返します。printf
すべてのフィールドは同じ形式で印刷されます。- そして最後に、
print
改行文字が行の末尾に配置されます。
これは、フィールド数に関係なく、フィールド数が他の行でも機能するため、より柔軟です。そして、1つの言語でしか実行できません(理解して維持するのは簡単です)。
でも:
$ awk 'for(i=1;i<=NF;i++){ printf("%-5s",$i) }; print ""}' infile
%-5.5s
5文字より長いフィールドを切り取るようにフォーマットを変更できます。
awkのprintfは、分解された文字をé
2文字として誤って計算します。 Unicodeクラスタの代わりにUnicodeコードポイント(一般的な問題)を計算するようです。
編集する コメントで次の追加質問に答えてください。
列 27 を定義する表の行を合計します。
必要なコードを追加するだけです。
$ awk '{split($0,a);
sum=sum+a[27];
for(i in a){ printf "%-5s", $i };
print ""
} END {
print "Sum of column 27 is =", sum }
' infile