1 AWKでWindows改行(CRLF)のCRだけ削除
テキストデータ処理が得意なプログラミング言語AWK(オーク)のことをネットで調べていたら、次の情報を見かけました(下図のとおり)。

上記のWebページは、⇒ https://note.com/brain_surfing2/n/nf431e47c6a19
Windows改行(CRLF)のCRだけを削除する方法を紹介しているページです。
そこには、 gsub(/\r$/, "", s) というコードが掲載されています。
私はこれを見て、「あれ、もしかして、これ間違ってないか?」って思いました。
ところが、実際に試してみると、このコードは正解でした。ちゃんと意図どおりに実行してくれます。疑ってゴメンなさい。
調べた結果、どうしてこれでよいのかの理屈が解明できたので、疑問点と併せて解説します(すぐに忘れてしまう将来の自分自身のために)。
2 どこが怪しかった?の疑問点
Windows PCで作成のテキストファイルの改行コードは「\r\n」で、文末は「\r」ではありません。なのに、なぜ「\r$」という記述でよいのか、これが私の疑問でした。
ちなみに、/\r$/ は正規表現であって、「\r」はキャリッジリターン(復帰)を表現するエスケープシーケンス、「$」は、末尾位置を示す正規表現メタ文字です。だから、/\r$/ は、「行末の \r にマッチ」という意味になります。末尾は\nであって、\rではない・・・はず、というのが疑問です。
このような疑問を持ったのですが、上記のとおり、その記述に間違いはありません。このコードで意図どおりのことが実現できます。
例えば、hoge.txtという名前のテキストファイルをWindowsで作成した上で、次のawkコマンドを実行すると、\rが除かれたhoge_Linux.txtが生成されます。
awk '{gsub(/\r$/,"");print}' hoge.txt > hoge_Linux.txt
3 なぜこれでよいのか、その理屈
なぜ上記のコードでよいのか、その理屈は次のとおりです。
awk は、(1) 入力を改行文字 \n でレコード分割する。 (2) そのとき \n は取り除かれる。 (3) しかし、\r はデータの一部として残る。
だから、Windowsの1行「文字列・・・\r\n」をawkが読むと、「文字列・・・\r」というレコードとして取り込まれる。つまり、行末が\rの各行のデータとなります。
そのため、gsub(/\r$/, "") によって、「行末の \r が削除される。」と、こういう理屈です。
4 Linux対応のテキストファイル生成の理屈
\rが削除される理屈は上記のとおりですが、それがLinux対応のテキストファイルとして生成されるのはなぜか。その理屈のカギは、printアクションです。
printは、「データ+"\n"」というように、データ末尾に"\n"を付加して出力します。これによって、"\r" を除去後に、printで "\n" が付加され、Linux対応のテキストファイルが出来上がります。
5 補足(おまけ)
上記の動作は、変数RSに入力レコード区切り文字として"\n"、また変数ORSに出力レコード区切り文字として"\n"が、それぞれ設定されていることが前提になっています。これがそれぞれのデフォルト値で、その各値は自由に変更が可能です。RS = "\n"、ORS = "\n" となっているデフォルト値を変えればよいのです。
それではまた次の記事で。
goosyun
