不可視文字
画面上に表示されないが、テキストデータ内に存在する文字の総称。ゼロ幅スペース、双方向制御文字、ソフトハイフンなどが含まれ、文字数カウントに影響を与える。
不可視文字 (invisible character) は、テキスト内に存在するにもかかわらず、画面上に視覚的な表示を持たない文字の総称です。制御文字 (改行、タブなど) とは異なり、不可視文字の多くはテキストの表示方法や処理方法に影響を与える「見えない指示」として機能します。文字数カウントにおいて、不可視文字は最も厄介な落とし穴の一つです。
Unicode には多数の不可視文字が定義されています。ゼロ幅スペース (U+200B) は幅のない空白で、長い単語の途中に挿入して改行可能位置を示します。ゼロ幅接合子 (ZWJ、U+200D) は前後の文字を結合し、絵文字の合成 (👨+ZWJ+👩+ZWJ+👧 = 👨👩👧) に使われます。ゼロ幅非接合子 (ZWNJ、U+200C) は逆に結合を防ぎ、アラビア語やペルシャ語で文字の接続を制御します。
双方向制御文字も不可視文字の一種です。左から右マーク (LRM、U+200E) と右から左マーク (RLM、U+200F) は、アラビア語やヘブライ語と英語が混在するテキストで書字方向を制御します。これらの文字は見えませんが、テキストの表示順序に大きな影響を与えます。
不可視文字が文字数カウントに与える影響は深刻です。ウェブページからテキストをコピー&ペーストすると、ゼロ幅スペースや双方向制御文字が紛れ込むことがあります。見た目は同じテキストなのに、文字数カウンターが異なる値を返す場合、不可視文字の混入を疑うべきです。たとえば「Hello」が 5 文字ではなく 7 文字とカウントされる場合、「H」と「e」の間にゼロ幅スペースが 2 つ挿入されている可能性があります。
セキュリティの観点では、不可視文字は悪意ある攻撃に利用されることがあります。ソースコードに双方向制御文字を挿入して、表示上は正常に見えるが実際には異なるロジックを実行させる「トロイのソース」攻撃が 2021 年に報告されました。ユーザー名やパスワードにゼロ幅文字を挿入して、見た目は同じだが異なる文字列を作る手法も知られています。
不可視文字への対策として、テキスト処理の前段階でサニタイズ (不要な不可視文字の除去) を行うことが推奨されます。正規表現 /[\u200B-\u200F\u2028-\u202F\u2060-\u206F\uFEFF]/g で主要な不可視文字を検出・除去できます。ただし、ZWJ は絵文字の合成に必要なため、一律に除去すると絵文字が分解されてしまいます。用途に応じた選択的な除去が必要です。