Panda Noir

JavaScript の限界を究めるブログでした。最近は幅広めに書いてます。

\sは本当に空白文字を網羅できているのか?

世の中にはやたらと空白文字があり、なんと30文字以上もあります!

/\s/はこんなにたくさんある空白文字の全てに対応しているのか?」という不安に駆られたので検証してみました。

スペース文字の一覧

http://anti.rosx.net/etc/memo/002_space.html

ここのページに書いてあるスペース文字それぞれが\sにマッチするか検証してみま した。

もう最初に書いてしまいますが、\sは全てを網羅しているわけではありませんでした。青くなっている方が\sにマッチした文字、赤くなっている方がマッチしなかった文 字です。

名称文字
FILE SEPARATOR[]
GROUP SEPARATOR[]
RECORD SEPARATOR[]
UNIT SEPARATOR[]
HANGUL JUNGSEONG A-EU[ᆣ]
HANGUL JUNGSEONG YA-U[ᆤ]
HANGUL JUNGSEONG YEO-YA[ᆥ]
HANGUL JUNGSEONG O-YA[ᆦ]
HANGUL JUNGSEONG O-YAE[ᆧ]
MONGOLIAN VOWEL SEPARATOR[᠎]
ゼロ幅空白[​]
ワード接合子[⁠]
HANGUL FILLER[ㅤ]
水平タブ (HT)[ ]
改行 (LF)[ ]
垂直タブ (VT)[ ]
フォームフィード (FF)[ ]
復帰キャリッジ・リターン (CR)[ ]
スペース[ ]
ノーブレークスペース[ ]
OGHAM SPACE MARK[ ]
EN QUAD[ ]
EM QUAD[ ]
EN SPACE[ ]
EM SPACE[ ]
THREE-PER-EM SPACE[ ]
FOUR-PER-EM SPACE[ ]
SIX-PER-EM SPACE[ ]
FIGURE SPACE[ ]
PUNCTUATION SPACE[ ]
THIN SPACE[ ]
HAIR SPACE[ ]
NARROW NO-BREAK SPACE[ ]
MEDIUM MATHEMATICAL SPACE[ ]
和字間隔[ ]
ゼロ幅のノーブレークスペース[]

ゼロ幅文字

名称文字
結合書記素接合子[͏]
ゼロ幅空白[​]
ゼロ幅非接合子[‌]
ゼロ幅接合子[‍]
記述方向制御(左から右へ)[‎]
記述方向制御(右から左へ)[‏]
LRE[‪]
RLE[‫]
PDF[‬]
LRO[‭]
RLO[‮]
関数適用[⁡]
不可視の乗算記号[⁢]
不可視の区切り文字[⁣]
行区切り文字[
]
段落区切り文字[
]
ゼロ幅のノーブレークスペース[]

マッチしない空白文字が思っていた以上にありますね。

仕様書を見てみる

仕様書を読んで確認をしてみます。

ECMA-262 8th Edition(ES2017)には\sについて次のような記述があります。

Return the set of characters containing the characters that are on the right‐hand side of the WhiteSpace or LineTerminator productions.

つまり、「\sは空白文字、あるいは行末文字にマッチする」ということです。

ECMAScriptで空白文字、行末文字は次のように定められています。

空白文字

  • U+0009(水平タブ)
  • U+000B(垂直タブ)
  • U+000C(フォームフィード)
  • U+0020(普通のスペース)
  • U+00A0(ノーブレークスペース)
  • U+FEFF(ゼロ幅のノーブレークスペース)
  • その他のUnicodeのSpace_Separator

その他のUnicodeのSpace_Separatorというのは次のとおりです(参考: https://www.compart.com/en/unicode/category/Zs)

  • U+1680(オガム文字のスペース)
  • U+2000(n幅の四角形)
  • U+2001(m幅の四角形)
  • U+2002(n字幅の空白)
  • U+2003(m字幅の空白)
  • U+2004(1/3m幅の空白)
  • U+2005(1/4m幅の空白)
  • U+2006(1/6m幅の空白)
  • U+2007(数字用空白)
  • U+2008(句読点用空白)
  • U+2009(狭い空白)
  • U+200A(非常に狭い空白)
  • U+202F(幅の狭いノーブレークスペース)
  • U+205F(中くらいの大きさの数学用空白)
  • U+3000(全角スペース)

行末文字

  • U+000A(改行)
  • U+000D(復帰キャリッジ・リターン)
  • U+2028(行区切り文字)
  • U+2029(段落区切り文字)

\sを表す正規表現

つまりまとめると次のようになります

// /\s/
/[\u0009\u000a\u000b\u000c\u000d\u0020\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]/

終わりに

というわけで、「\sは世の中のすべての空白文字を網羅しているわけではない」と分かりました。

まあぶっちゃけ半角スペース・全角スペース・タブに対応しておけば十分ですよね。ここまで対応しなければいけない場面は早々ないと思うので、通常の用途なら\sで十分です。