双方向制御文字(Bidi)とは?混入リスクと安全なコピペ手順

双方向制御文字(Bidi)とは?混入リスクと安全なコピペ手順

“見た目は同じなのに検索がヒットしない”“レビューで謎の差分が出る”──その原因が 双方向制御文字(Bidi) の可能性は高いです。本記事ではBidiの基礎、混入で起きる不具合、安全なコピペとレビューの手順をまとめます。最短での検出・除去は Invisible Cleaner が便利です。


Bidi(双方向制御)とは

アラビア語・ヘブライ語のように 右→左(RTL)、英語や日本語のように 左→右(LTR) が混在する文章において、表示方向や文字の並びを制御するための特殊文字(不可視文字)です。
代表的なものは以下のとおりです(名称 / 役割 / 例):

  • LRE/RLE (U+202A/U+202B):以降を LTR/RTL として埋め込み表示
  • LRO/RLO (U+202D/U+202E):以降を LTR/RTL として 強制 表示(順序固定)
  • PDF (U+202C):埋め込みや上書きを終了
  • LRM/RLM (U+200E/U+200F):長さ0の LTR/RTL マーク(細かな流れ調整)
  • LRI/RLI/FSI/PDI (U+2066/U+2067/U+2068/U+2069):分離された埋め込み(近年の安全な制御法)
  • ALM (U+061C):アラビア文字用マーク(方向を補助)

本来は正しいレイアウトのために必要ですが、意図せぬ混入で「見た目」と「実体(コードポイント列)」がズレ、トラブルを招きます。


何が起こる?(表示と実体のズレ)

例:見た目が同じでも文字列が違う

見た目:  abc(); // call
実体A:  a b c ( ) ;  / /   c a l l
実体B:  a b c ( ) ;  / /  l l a c

上は極端な例ですが、RLO/LRO 等によって表示順が変わると、検索・一致判定・パース・差分比較が意図通りに動きません。

よくある不具合

  • 検索・置換が当たらない(実体の順序が異なる)
  • リンクやURL、タグが壊れる(属性名中のBidiでパース崩れ)
  • コードレビューで不可解な差分(見た目では同じなのに変更扱い)
  • セキュリティ・リスク(コメント内から実行部を“見えにくく”する等)

どこで混入する?

  • SNSやWebサイトからの コピペ(翻訳・要約ツールも含む)
  • メール件名/署名 の引用
  • 多言語資料 の編集(右→左言語混在)
  • Word/Docs/コードエディタ間の 相互コピー(書式付き→プレーン化の過程で)

安全なコピペ手順(最短ルート)

  1. プレーンテキストで貼り付け(「形式を選択して貼り付け」やプレーン化ショートカットを使用)。
  2. 検出→プレビュー
    • ブラウザの Invisible Cleaner に貼り付け、Bidi を検出。
    • 差分プレビューで意味が変わらないか確認。
  3. 最小限の置換:RLO/RLE/LRO/LRE/FSI/LRI/RLI/PDI 等の制御目的のない混入のみを削除。
  4. 再検証:検索や整形、ビルドが期待通り動くかを再チェック。

ポイント:無差別な削除は厳禁。LTR/RTL を本当に必要とする文章では、LRM/RLM/FSI…が意味を持つことがあります。


開発時・レビュー時のチェックリスト

  • 差分は 表示用UIだけでなく Raw 表示 でも確認したか
  • エディタの 不可視文字表示 をONにしているか
  • 検索は コードポイント(正規表現) でも行ったか
  • 外部テキストの流入(翻訳・SNS)部分は 一括検査 したか
  • 変更の直前直後で ビルド/テスト を回して差分を確認したか

簡易検出パターン(JS/PCRE系想定)

[‪-‮⁦-⁩‎‏؜]   # Bidi制御の代表集合
  • ‪-‮ … LRE/RLE/LRO/RLO/PDF
  • ⁦-⁩ … LRI/RLI/FSI/PDI
  • ‎‏ … LRM/RLM
  • ؜ …… ALM

まずは 検出のみ 実行し、削除はプレビューで問題ない箇所に限定しましょう。


チームに導入する運用

  • コミットフック(pre-commit) で検出:対象拡張子に上記正規表現を当て、ヒット時は警告。
  • リンター/CI に“不可視文字チェック”を追加:ログで位置を明示。
  • 規約テンプレ:PR説明に「外部からのコピペ部分」「多言語テキスト」の有無を明記。
  • 教育:短い社内ドキュメントで Bidiとは対処フロー を共有。

まとめ(運用の勘所)

  • Bidi は“正しい表示”のための仕組みだが、意図せぬ混入は不具合やリスクに直結。
  • コピペは プレーン化→検出→最小置換 の三段階で安全に。
  • レビューは Raw表示+自動チェック を併用して見落としを減らす。
  • 迷ったら Invisible Cleaner で見える化してから判断する。

付録:主なBidi制御文字の早見表

文字 コードポイント 役割の概要
LRE U+202A LTR 埋め込み開始
RLE U+202B RTL 埋め込み開始
PDF U+202C 埋め込み終了
LRO U+202D LTR 上書き(強制)
RLO U+202E RTL 上書き(強制)
LRM U+200E LTR マーク
RLM U+200F RTL マーク
LRI U+2066 分離LTR埋め込み開始
RLI U+2067 分離RTL埋め込み開始
FSI U+2068 分離 埋め込み(方向未定)開始
PDI U+2069 分離埋め込み終了
ALM U+061C アラビア文字向けマーク

実運用では、FSI/LRI/RLI/PDI を中心とした「分離された埋め込み」の利用が推奨されるケースが多く、安全性が高い傾向にあります。