このスクリプトの解説を続けます。
{gsub(/"/,"")}
{gsub(/[ ][ ]+/,"")}
{print}
2行目の{gsub(/[ ][ ]+/,"")}はもう少し複雑です。//の中が一文字ではなくて「二つ以上連続した半角空白」を意味する表現になっています(脚注1)。カンマの後ろは1行目と同じで何も文字を指定していません。対象文字列の指定も省略しているので結局「二つ以上連続した半角空白をレコードから消去しなさい」という意味です。
ここまでで置換の処理はできました。しかし「sub, gsubがやるのはここまでです」。これは大事なことで、この関数は対象文字列(この場合は$0)を書き換えますが、結果の出力までは面倒見てくれません。またこの関数が返す値も「置換された文字列そのもの」つまり「作用の結果を返すのではなくて」、「いくつ置換したか」です。したがって置換した結果を得るには{print}で明示的に出力してやらねばなりません。printはもうお馴染みで、このように単独で使うと$0を出力します。
以上より、このスクリプトの出力はこんな感じです。
960105,19,960001,森田健作,M, 57,6,0,0,960105,7.8,1.69,25,21,333,138,25 ,5.2,0.6,19.4,4.1,223,80,140,0.1,5800,514,15.9,48.4,29.1,83 960105,20,960002,和田孝雄,M, 56,6,0,0,960105,7.1,1.96,23,32,225,118,23, 2.6,0.6,21.0,5.8,163,50,204,0.1,6700,543,17.0,49.3,21.6,78(注)70桁で改行しています。
前々回に「関数の"作用"と"返す値"は区別せよ」と書いたのはこういうことです。sub, gsubの作用は「文字列の置換」で、返す値は「置換した個数」です。関数の作用で置換された文字列そのものを返すわけではありません。しかも文字列は見えないところでちゃんと置き替わっています。
例えば次のスクリプトを実験してみてください。
BEGIN{
a="Hellow Miniren net members!";
print a;
b=sub(/Miniren/,"min-min",a);
print b;
print a;}
出力はこうです。
Hellow Miniren net members!
1
Hellow min-min net members!
print bでなんとなく Hellow min-min net members! と出力されそうですが(と思うのは私だけ?)、実際は 1 とでるだけです。
関数の作用(およびその結果)と返り値の関係は混乱しがちなところですから、くれぐれもご注意ください。
(脚注1)
このような一連の書き方を「正規表現」といいます。以前ちょこっと紹介したことがあります。後に詳しく触れますので当面は読み飛ばしていただいて結構です。
初出 NIFTY-Serve「みんみんネット」1996/09/18 (Wed) 14:00:53