2023年12月10日: gawk 「-k」オプションなら クオートあり、改行あり CSV を正しく扱える件
GNU AWK のオプション -k
または --csv
を使うと、クオートあり、改行ありの CSV を正しく扱えることが分かったんでそのお試しメモ。
CSV 処理といえば FS=","
だけど…
よくあるのが FS
を ","
に設定する使い方。クオートがないCSVだったり、データとして改行を含まないCSVならこれで十分だけど、Excel だとかが出力する CSV って往々にして、クオートがあったり、データとして改行を含むもの。そうなるともう awk は選択しとしては現実的じゃなくなって、Perl でモジュールを使うだとかをすることになる。やりたいことはシンプルなのにお手軽に AWK を使えないのは残念過ぎる。
GNU AWK の「-k
」オプション
GNU AWK のオプション -k
または --csv
を使うと、クオートあり、改行ありの CSV を正しく扱えるようになってた。いつの間にか。いくつかの入力データで試した。
お試しに使ったコードはこれ
{for (f=1 ; f<=NF ; ++f) printf "(%s)\n", $f}
基本サンプル
フィールド中のカンマも改行も期待どおりに処理されるのを確認できた。
% (echo ',"string contains ' ; echo 'Newline, and ' ; echo 'Newline",after comma') \
| gawk -k -f print-fields.awk
()
(string contains
Newline, and
Newline)
(after comma)
%
いい感じ。「and
」に続くスペース文字の様子もみてみたら、ちゃんとできてた。
% (echo ',"string contains ' ; echo 'Newline, and ' ; echo 'Newline",after comma') \
| gawk -k -f print-fields.awk \
| sed -e 's/$/|/'
()|
(string contains |
Newline, and |
Newline)|
(after comma)|
%
NR
はどおなる?
入力データのフィールド中に改行文字がある場合でも NR
は増えてない。いいねっ。😀
% (echo ',"string contains ' ; echo 'Newline, and ' ; echo 'Newline",after comma') \
| gawk -k '{for (f=1 ; f<=NF ; ++f) printf "[NR=%d,f=%d]: (%s)\n", NR, f, $f}'
[NR=1,f=1]: ()
[NR=1,f=2]: (string contains
Newline, and
Newline)
[NR=1,f=3]: (after comma)
%
ダブルクオート中のダブルクオート「""
」
Excel が出力する CSV の表記法で、ダブルクオート中のダブルクオートを「""
」表記する件。これにも対応してるっぽい。
% echo ',"""quote char in quoted string""",' \
| gawk -k -f print-fields.awk
()
("quote char in quoted string")
()
%
カンマの直後が「"
」でない場合
これも Excel 方式に対応してるみたい。
% echo ', "quoted string starts end ends with space" ,' \
| gawk -k -f print-fields.awk
()
( "quoted string starts end ends with space" )
()
%
「"
」が閉じてない最後の行
これはファイルの一番最後に「"
」がある場合と同じように処理されるっぽい。
% echo ', "unclosed quoted string starts with space,after comma' \
| gawk -k -f print-fields.awk
()
( "unclosed quoted string starts with space)
(after comma
)
%
カンマの直後が「"
」でなくて、途中に「,
」があって、「"
」が閉じてない場合
この場合は、要するに、クオートされてない裸のフィールドと同じ処理になってるみたい?
% echo ', "unclosed quoted string starts with space,after comma' \
| gawk -k -f print-fields.awk
()
( "unclosed quoted string starts with space)
(after comma
)
%
改行シーケンス CR
LF
問題
Excel から出力した CSV に対応してるみたい?改行シーケンス CR
LF
問題はどおなのか、ためしてみたら、実行してる環境が Cygwin だからなのか、入力データ中の CR
が無視されたみたいな結果になった。
% printf 'begin,"Hello,\r\nWorld.!",end\r\n' \
| gawk -k -f print-fields.awk \
| sed -z -e 's/\r/<CR>/g' \
| sed -z -e 's/\n/<LF>/g'
(begin)<LF>(Hello,<LF>World.!)<LF>(end)<LF>%
おしまい
Excel から出力される CSV にもシッカリ対応できてるから、これはかなり実用性が上がったともう。いいねっ。