改行コード

改行を表す制御文字。LF (Unix)、CR (旧 Mac)、CRLF (Windows) の 3 種類がある。

改行コードとは、テキストデータにおいて行の終わりと次の行の始まりを示す制御文字です。主に LF (Line Feed, U+000A)、CR (Carriage Return, U+000D)、CRLF (CR と LF の 2 文字の組み合わせ) の 3 種類があります。これらの名称はタイプライターの動作に由来しており、CR は印字ヘッドを行頭に戻す動作、LF は用紙を 1 行分送る動作を意味していました。コンピュータの黎明期にこの概念がそのまま引き継がれ、現在に至っています。

OS ごとに標準の改行コードが異なります。Unix/Linux/macOS は LF、Windows は CRLF、旧 Mac OS (Classic Mac OS、Mac OS 9 以前) は CR を使用します。この違いはファイルの互換性に直接影響し、異なる OS 間でテキストファイルをやり取りする際に問題を引き起こすことがあります。Git では core.autocrlf 設定で改行コードの自動変換を制御でき、チーム開発では .gitattributes ファイルでリポジトリ全体の改行コードポリシーを統一するのが一般的です。

プログラミングにおいて、改行コードの違いはしばしばバグの原因になります。ファイルを行単位で読み込む際に LF のみを想定していると、CRLF のファイルでは各行の末尾に CR が残ってしまいます。正規表現で行末を $ でマッチさせる場合も、改行コードの違いによって期待どおりに動作しないことがあります。堅牢なテキスト処理を実装するには、\r\n\n\r のすべてに対応する設計が必要です。

同じ正規表現でも言語によって行末の解釈が違います。CRLF を含む文字列に対して複数行モードで a$ を照合すると、JavaScript の /a$/m は真を返しますが、Python の re.search("a$", s, re.M) はマッチしません。Python の $ は LF の直前だけを行末とみなすため、a の後ろに残った CR が邪魔をするからです。読み込み側の自動変換も見落としがちです。Python の open() は既定で改行の自動変換 (universal newlines) が働くため、CRLF のファイルを読んでも文字列としては LF に置き換わった状態で渡ってきます。元の改行をそのまま扱いたい場合は newline='' を指定します。逆に str.splitlines() は CR・LF・CRLF だけでなく垂直タブ (U+000B) や U+2028 のような文字でも行を切るため、改行コードだけで切りたいなら分割する文字を明示したほうが安全です。

改行コードはさまざまなプロトコルや仕様でも規定されています。HTTP/1.1 のようなテキスト形式のプロトコルではヘッダーの区切りに CRLF が使われ、CSV ファイルの仕様 (RFC 4180) でも各レコードは CRLF で区切ると定義されています。SMTP (メール送信プロトコル) は行を CR に続く LF で終端すると定め、それ以外の文字や並びを行終端として認識・生成してはならないとしています (RFC 5321)。一方、JSON では文字列の中に U+0000 から U+001F の制御文字をそのまま置くことが禁じられているため (RFC 8259)、改行は \n のような 2 文字のエスケープか \u000A のような 6 文字表記で書きます。取得したデータの改行をそのまま埋め込んだ JSON は、見た目には改行しているだけでもパースエラーになります。

規格の細部はそのまま実務の落とし穴になります。RFC 4180 は、ファイルの最後のレコードには末尾の改行があってもなくてもよいとしています。さらに、改行や二重引用符・カンマを含むフィールドは二重引用符で囲むと定めているため、CSV は改行で単純に分割できません。引用符の内側にある CRLF はレコードの区切りではなくフィールドの中身であり、自分で行単位に切ってからカンマで分ける実装はここで壊れます。CSV を扱うときは行分割から自作せず、引用符の解釈まで行うライブラリに任せるのが安全です。

よくある誤解として、改行コードは目に見えないため「どれでも同じ」と思われがちですが、実際にはバイト数が異なります。LF は 1 バイト、CRLF は 2 バイトであるため、大量のテキストデータでは改行コードの違いがファイルサイズに影響します。また、エディタやツールによっては改行コードの混在 (同一ファイル内に LF と CRLF が混在する状態) を検出・修正する機能を備えています。末尾の改行の有無も結果を変えます。改行を「行の終端」とみなして数える道具では、最後の行に改行が無いファイルはその行が数に入りません。a・改行・b の 3 文字だけのファイルを wc -l に渡すと、見た目は 2 行でも 1 が返ります。

文字数カウントの観点では、改行コードを文字数に含めるかどうかが結果に影響します。多くの文字数カウントツールでは改行を 1 文字としてカウントしますが、CRLF を 1 文字と数えるか 2 文字と数えるかはツールによって異なります。正確な文字数を把握するには、使用しているツールの改行コードの扱いを確認しておくことが重要です。たとえば JavaScript で "a\r\nb".length は 4 を返し、CRLF は 2 文字として数えられます。同じ内容を LF にすれば 3 です。入力文字数に上限があるフォームでは、Windows で作った改行入りの文章を貼ると、数えている文字が同じでも想定より早く上限に達することがあります。

この記事を共有