awkを仕事で扱うCSVファイルの編集に使用している事を先日のエントリーにも記しましたが、実に便利なコマンドです。今日は楽天への商品アップロードCSVファイルからコントロールフラグをカギにしてレコードを抽出し、そのレコードだけをawkで取り出すという実に簡単なawkの処理をしました。
社内ではシステムからCSVを生成してそれをアップロードしています。その中から削除した商品レコードだけを取り出す必要が生じたのです。
しかし、楽天の商品データitem.csvには商品説明欄もあり、ここに改行コードが入っているので、そのままではawkで処理できません。なぜならawkは改行コードをRS(レコードセパレータ)として扱うからです。もちろんRSを別の文字列などに変更することもできますが、改行とレコードの末端との区別が付く様に加工してやらなくてはなりません。
少し悩みましたが発想の転換をすることにしました。レコードの末端ではなく先端にマーカーをつけることにしました。awkで処理できる形に成型する作業ですから、テキストエディタ(正規表現置換)で行いました。
規則性を再確認してみましたが、レコードの先端には”(ダブルコーテーション)とコントロールフラグが入っています。
"u","xxxxxxxx","yyyyyyyyy" "d","vvvvvvvv","nnnnnnnn" "n","ppppppp","ooooooo0"
こんな感じです。uはアップデート(更新)、dはデリート(削除)、nはニュー(新規)という意味らしいです。
商品説明のカラムに改行が入っていてこの規則性(1レコード=1行)が成り立ってない為に、awkがそのままでは使用できないので、第一カラムにマッチした場合は、そこがレコードの先端だと判断する事にしました。つまり正規表現では下記の様になると思います。^は先頭を意味していますし、”は特殊文字なので\でエスケープが必要です。
/^\"u\"|^\"d\"|^\"n\"/
ただ、この正規表現にマッチした場合、その先端にマーカー@を付けるとした場合の置換方法を私は知りません。仕方ないので一つずつ実行するしかありません。置換作業を三回繰り返しです。
/^\"u\"/ >>> @"u" /^\"d\"/ >>> @"d" /^\"n\"/ >>> @"n"
とにかくこれでレコードの頭に@が着きました。
次に改行コード(\n)を削除します。これも正規表現でマッチさせられますので、\nを何もナシに置換します。改行が削除されるので、正常に出来たら一行のデータになってしまいます。
ここで先ほど付けた@の出番です。@を改行(\n)に置換すれば、目的は達成です。これで1行=1レコードのCSV書式となります。なーに、商品説明欄は要らないのですから改行コードを抹殺しても構わないのです。
今回はdフラグを付けたレコードのみを抽出したいのです。awkなら$1==”d”で簡単にチェック出来ます。実際はダブルクォーテーションをエスケープしなくてはならないので円マークを前に付ける必要がありますけどね。
$1==\"d\" {print $0;}
今回の作業の様に、awkだけでは解決しないケースは結構あります。PerlやRuby、PHPなどではCSVのカンマ区切りと、データを””で囲っているという構造に対応しているので、改行コードが入っていてもそのまま処理できるそうです。awkは古い言語ですから仕方有りません。
その代わり、プログラミングビギナーにも比較的容易で、目的を達成できるのがメリットです。柔軟性が無いというのがむしろ簡素だという点でプログラミングが苦手な私はawkを評価しています。
もちろん更にawkの使いこなしを理解すれば、今回のケースでもawkだけで処理できると思います。しかし私はプログラマーでは無いので、何がなんでもawkだけで処理を完結させる必要はありません。他の方法と組み合わせてでも、仕事をなるだけ早く正確に終わらせるのが一番の課題です。(もちろん今後もawkについての学習は進めますけどね。)
でも、もしどうしてもawkでは話にならない、ということになったらその時は私も成長したと言うことで、次へステップアップする時期だということでしょう。それは現時点想定できませんがもしそうなったら喜ばしいことです。
コメント