hnwの日記

ファイル末尾の連続する改行を取り除く

テキストファイルの末尾に改行がたくさんついてたり、逆に1個もついていなかったりすることってありますよね。たくさんあるファイルについて、末尾改行1個だけの形に統一したいなー、と思ったら意外と苦労したので紹介します。


本当はもっとシンプルに書けそうな気もするんですが…。

perl -i.bak -pe 'BEGIN{undef $/}s/([^\n])\n*$/$1\n/;' hoge.txt


ポイントは「undef $/」です。$/は入力の区切り文字を意味し、デフォルトでは改行文字となっています。これを未定義値にすると、1行を取得しようとしてファイル全体を取得するので、改行を跨いだ置換が可能になります(ファイルが巨大なときには死にかねませんが、手元で作業する分にはいいでしょう)。


ただ、改行を含む文字列の置換ははまりどころが多いので注意が必要です。僕だけかもしれませんが、毎度のことなのにsフラグとmフラグについて混乱したりします。今回の例ではmをつけるとうまく動きませんが、普段はmフラグの付け忘れで混乱するように思います。「man perlre」を参照してください。


これをxargsで回せば作業は完了ということになります。

find . -name '*.txt' | xargs perl -i.bak -pe 'BEGIN{undef $/}s/([^\n])\n*$/$1\n/;'


追記:2009/12/27 11:40)また、*.phpのファイル末尾の「?>」を、前後の余計な空白文字列ごと削りたい場合は次のように書けます。「?>」以降に余計な改行が含まれていて困る、なんて場合に便利かと思います。

find . -name '*.php' | xargs perl -i.bak -pe 'BEGIN{undef $/}s/\s*\?\>\s*$/\n/;'