LoginSignup
6
5

More than 3 years have passed since last update.

AWKでprint $0 時にOFSの設定を反映する(区切り文字の指定)

Posted at

何をしたいか

awkで、一行全体の表示print $0時に、出力ファイル区切り文字OFSを指定しても機能しない現象を何とかしたい。

状況

テーブルの区切り文字を変換して出力したい、処理結果をカンマ区切りで出力したい…等

例)こんなCSVを用意する。これをタブ区切りに変換して出力したいとする。

$ cat test.csv
a,b,c,d,e,f
1,32,6543,45,4,45
2,45,521,343,1,211
3,32,321,641,-2,377
4,45,56,939,-5,543
5,32,532,1237,-8,709
6,45,7,1535,-11,875

現象

$ gawk 'BEGIN {FS=","; OFS="\t";} {print $0}'
a,b,c,d,e,f
1,32,6543,45,4,45
2,45,521,343,1,211
3,32,321,641,-2,377
4,45,56,939,-5,543
5,32,532,1237,-8,709
6,45,7,1535,-11,875 # 区切り文字が変わっていない!

対処

$つき変数に対して何らかの適当な代入処理を行う。$1=$1; 程度の簡単なものでよい。

$ gawk 'BEGIN {FS=","; OFS="\t";} {$1=$1; print $0}'
a       b       c       d       e       f
1       32      6543    45      4       45
2       45      521     343     1       211
3       32      321     641     -2      377
4       45      56      939     -5      543
5       32      532     1237    -8      709
6       45      7       1535    -11     875 # タブ区切りが反映された

原因

ここまで書いて同一内容の先行記事を見つけた。

これでは差分がないので、少し原因を調べてみることにする。

調査結果

  • フィールド$0の再構成タイミングはいつか、という問題に尽きる。

The GAWK Manual Edition 0.15 より
入力ファイルの読み込み > フィールド分割の指定 の節に、ほとんど回答になっている以下の記述がある。

先頭や末尾にある連続した空白をはぎとるという動作は、$0が再計算されたときには常におこなわれる。したがって、

echo '   a b c d' | awk '{ print; \$2 = $2; print }'

このパイプラインは次のような結果となる。

   a b c d
a b c d

最初のprint文は読んだままのレコードを、行頭の空白を含んだ形で出力する。 \$2に対する代入で\$0 は\$1 から\$NFまでをOFSを 区切りとして連結した結果に再構成される。

なお、慣れていない人向けに書くと、単にprint と書くのはprint $0 の省略形である。

つまり、(明確に記述されているわけではないが)単純にprint $0を実行するだけでは$0は再構成されないことが推察される。再構成されない限りOFSは反映されず、元の文字列がそのまま出力されることになるというわけである。

フィールド代入の結果元のデータを変更せず、かつ$0の再構成を誘発し、最も短く書ける文が$1=$1;というわけだ。

ちなみに、$0=$0;は再構成を発生させないので、今回の問題の解決には効果がない(試されたし)。

執筆理由

久しぶりにawkを使ってトラブった。基本的な内容だが、意外に日本語記事が少なかったため。
WindowsでもWSLが使えるようになって、シェルのツールがかえって便利になってきつつあるので、こういった温故知新ツールの出番が増えるかもしれませんね。

6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5