【正規表現】改行コードの落とし穴(覚え書き)


PenCakeという日記アプリのパーサーを書いていて、改行コードへの無知のためにハマった話です。
覚え書きなので文章としてはグダグダです。


本文

まずこんな内容のテキストファイルがあって、

Hello

Mon, Dec 20, 2021 6:25 PM

Hello, Pencake!
...
...

この3つの要素(上から順にタイトル、日時、本文)を別々に取り出したくて、

(.*)\n\n(.*)\n\n([\s\S]*)

こんなパターンを書いたが、マッチしない。

紆余曲折の後、Xcodeのデバック機能でランタイム上のテキストを表示させてみると、改行文字が\nではなくて\r\nの2文字になっているのを発見。

調べてみると、改行コードは\nだけじゃなくて、以下の3種類があるらしいということがわかった。

名前 記号 意味 OS
LF(Line Feed) \n キャレットを左端へ戻す UNIX系全般
CR(Carriage Return) \r キャレットを次の行に移す 旧MacOS
CRLF(CR + LF) \r\n キャレットを左に戻してから次の行へ移動 Windows系全般

どうやらそのアプリの使用上、エクスポートしたファイルの改行コードはCRLFになるようだった。iOSアプリなんだったらLFにしてくれや。

なので改行コードが上記のいずれであっても正確にマッチするように、2つ連続した改行コードは

(\n{2}|(?:\r\n){2})

と表せるので、結果的に

(.*?)(\n{2}|(?:\r\n){2})(.*?)\\2([\\s\\S]*)

として解決。

追記

このNSRegularExpressionのラッパーライブラリが便利です。

https://github.com/crossroadlabs/Regex

参考リンク

https://www.javadrive.jp/regex-basic/
https://qiita.com/tossh/items/635aea9a529b9deb3038
https://qiita.com/uhooi/items/dc74ff3434aecb17faa2