つれづれ電脳記(日くらしPCに向かひて)

つれづれなるままに、日くらしPCに向かひて、その悪戦苦闘ぶりをそこはかとなく書き付くるおじさん。たまに雑談[管理人:goosyun]

つれづれなるままに、日くらしPCに向かひて、デジタル関係の悪戦苦闘ぶりをそこはかとなく書き付くるおじさんです。
たまに雑談してます。連絡・問い合わせフォームは、ページ最下部に置いています。[著者(運営人):goosyun]

(当ブログには本文中に広告リンクが含まれています。)

プログラミング言語AWKでWindows改行をLinux改行に置換

 


1 AWKでWindows改行(CRLF)のCRだけ削除

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

改行コードCRを削除するgsubコード

    上記の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