見た目が同じ文字列なのに一致しない原因の調べ方
コピーした文字列が検索や照合で一致しないときは、原因が4つの層に分かれます。見えない文字・濁点の持ち方・全角と半角・字体の指定を、確かめる順番に並べて切り分け方を説明します。
公開読了目安 約5分
この記事の要点
- 原因は見えない文字・濁点・幅・字体の4層に分かれる
- 文字数が一致するかどうかで最初の当たりが付く
- 貼り付け直しても直らないなら濁点の持ち方を疑う
- 検索欄で通らないときはシステム側の正規化も疑う
- 原因の層が決まってから直し方を選ぶと手戻りがない
目次
コピーした文字列が検索に引っかからない。2 つのセルを見比べても同じなのに、表計算では違うと判定される。この手の食い違いは、原因が 4 つの層に分かれます。
上から順に確かめると、たいてい 2 つ目までで見つかります。まずは文字数を比べるところから始めてください。
最初の分かれ道は「文字数が合うかどうか」
2 つの文字列の長さを比べます。ここで結果が割れます。
| 見えかた | 疑うところ |
|---|---|
| 長さが違う | 見えない文字がまざっている |
| 長さは同じで、かなが関係する | 濁点や半濁点の持ち方が違う |
| 長さは同じで、英数字や記号が関係する | 全角と半角がまざっている |
| 長さは同じで、漢字が関係する | 字体の指定が付いている |
まずは見た目の文字数で比べます。ここで差が出なくても、コードポイントの数では差が出ることがあります。
濁点の分解(層 2)と字体の指定(層 4)は見た目の数を変えないので、その 2 つはコードポイントの数で見ます。
層1: 見えない文字がまざっている
いちばん多い原因です。Web ページや PDF からコピーすると、幅を持たない文字がそのまま付いてくることがあります。
よく見つかるのは次の 4 つです。
- ゼロ幅スペース(U+200B) — 幅がゼロの区切り。折り返し位置の指定に使われる
- 改行しない空白(U+00A0) — 見た目は半角スペースだが別の文字
- BOM(U+FEFF) — ファイルの先頭に付く印。コピーで先頭に紛れ込む
- 全角スペース(U+3000) — 半角スペースのつもりで入っていることがある
これらは目で探せません。文字コード調査ツールに貼り付けると、何の文字が何個どこにあるかが一覧で出ます。
直し方
原因の文字が分かったら、置換で消すのが確実です。ただし全角スペースのように意味のある空白は、消さずに半角へ置き換えるほうが安全です。
層2: 濁点や半濁点の持ち方が違う
「が」という 1 文字には 2 つの書き方があります。1 文字ぶんの U+304C と、「か」に濁点を足した 2 文字ぶんです。
画面ではどちらも同じに見えます。ところが比較すると別物になります。この違いは Mac で作られたファイル名や、一部のシステムから出力されたデータでよく起きます。
見分けるにはコードポイントの数を見ます。「がぎぐ」は合成済みなら 3 ですが、分かれていると 6 になります。
見た目の文字数(書記素)はどちらも 3 のままです。この層だけは見た目の数で判断できません。
直し方
Unicode 正規化の NFC をかけると、分かれた濁点が 1 文字にまとまります。表計算なら合成済みの文字を貼り直すのが手早い方法です。
住所録や名簿でこの状態が広く混ざっているときは、全角半角変換ツールや表記ゆれの整理と合わせて進めてください。
層3: 全角と半角がまざっている
英数字と記号には全角と半角の 2 つの形があります。A と A、1 と 1、( と ( はそれぞれ別の文字です。
入力する人の環境によって、どちらが入るかが変わります。同じ人が入力しても、日付は半角で電話番号は全角、ということが起きます。
ハイフンはさらに厄介です。半角ハイフン・全角ハイフン・長音記号・ダッシュが混ざり、見た目ではほとんど区別が付きません。
直し方
一括で寄せるなら全角半角変換ツールが向きます。1 件だけ確かめたいときは、その文字の番号を見て違いを確定させてください。
層4: 字体の指定が付いている
漢字には、同じ文字に対して字体を指定する目印を付ける仕組みがあります。異体字セレクタと呼ばれる、それ自体は幅を持たない文字です。
葛 や 辻 のような字でよく使われます。片方だけに指定が付いていると、見た目はほぼ同じでも別の文字列として扱われます。
この目印はコピーのときに落ちることも残ることもあります。だから同じ画面から取ったはずのデータでも食い違いが出ます。
直し方
システムが字体の違いを保持する必要がないなら、目印を外して統一するのが単純です。逆に戸籍関連のように字体が意味を持つ場合は、外さずに比較の側を合わせてください。
システム側の正規化で消えることもある
入力した文字列が、保存される前に変換されている場合があります。ログイン欄や検索欄では、NFKC という正規化がかけられることがよくあります。
この処理は ㍿ を「株式会社」に、全角の A を A に開きます。入力した文字列と保存された文字列が別物になるため、「入れたはずの値で検索しても出てこない」という状態が生まれます。
どの形で変わるかは文字によって違います。4 つの正規化形を並べて見れば、どこで開かれるのかが分かります。
確かめる順番のまとめ
- 2 つの文字列の見た目の文字数を比べる
- 差があれば、見えない文字を一覧で探す(層 1)
- 差が無ければ、コードポイントの数を比べる
- コードポイントに差があれば、かなは層 2・漢字は層 4 を見る
- どちらの数も同じなら、英数字と記号の全角半角を見る(層 3)
- 該当する層の直し方を選び、直した後にもう一度番号を突き合わせる
順番を飛ばして置換から始めると、消してはいけない文字まで消すことがあります。原因の層を決めてから手を動かすほうが、結果として早く終わります。
補足: 開発者の方へ
比較の前に String.prototype.normalize('NFC') をかけておくと、層 2 の食い違いは大半が消えます。検索インデックスと入力の両方に同じ形を適用することが要点です。
見えない文字の除去は、範囲を絞った置換にしてください。書式制御文字(一般カテゴリ Cf)をまとめて落とすと、絵文字の連結や字体の指定まで壊れます。
文字数の比較には length ではなく Intl.Segmenter の書記素数を使います。BMP 外の文字や結合文字があると、length は人の感覚と 2 倍以上ずれることがあります。
あわせて読みたい
同じテーマ・関連ツールの記事です。