awkで$0出力するときにOFS指定が無視られる問題
awkでOFS指定しても出力のセパレータが無視される時がある問題がやっと解決しました.
やりたいこと
- 何らかのセパレータで区切られたcsvファイルの中から,特定の条件を満たす行を,セパレータを変えて出力する
まぁ,こう言われればみんなawkでやろうとしますよね?そうでもない?
例えば以下のようなカンマ区切りのcsvファイル
a,b d,c a,e e,d
この中から,一つ目のフィールドが"a"の行のみ,セパレータをカンマからプラスに変えて出力したいとします.
つまり,
a+b a+e
が望む形.
この時,とりあえず思いつくのは,
% awk -F "," 'BEGIN{OFS="+"}{ if($1=="a"){print $0}}' test.csv
ですよね.OFSは出力セパレータ.始めに出力セパレータにプラスを指定しておいて,$0で全フィールド出力.
ところが,これだとうまくいきません.結果はこうなります.
a,b a,e
ちゃんと条件は取れているのですが,セパレータが変更されていません.ですが,実は以下のように書くと意図した通りに動きます.
% awk -F "," 'BEGIN{OFS="+"}{ if($1=="a"){print $1,$2}}' test.csv
結果が以下です
a+b a+e
何故$0(全出力)ではうまくいかず,$1,$2と全部指定するとうまくいくのかずっと謎でした.この例ではフィールドが二つだからいいですが,多くなってくると,さらにフィールドの数が可変になってくると,for文を使って全フィールド出力することになり,たったこれだけの処理なのにやけにコマンドが汚くなります.
実は理由は今でも謎ですが,以下のようにするとうまくいくことが分かりました.
% awk -F "," 'BEGIN{OFS="+"}{$1=$1; if($1=="a"){print $0}}' test.csv
結果が以下です
a+b a+e
上記のように,$1=$1というおまじないを入れることでうまくいくようになります.
理由はかなり謎ですが,どうやら$1=$1とすることでカラムの再構成が行われてどうとか・・・?
どちらにせよ,$0で指定する場合と$1,$2...$NFで指定する場合で結果が違うというのは何か気持ち悪いです.