Posted at

Javascriptで全角スペースと半角スペースを正規表現で指定する


Irregular whitespace not allowed

Vue.jsの開発中にLintのエラーが出た。

 error  in ./src/App.vue

✘ http://eslint.org/docs/rules/no-irregular-whitespace Irregular whitespace not allowed
/Users/masa/.ghq/52.197.1.134/SumasapoWeb/web/src/App.vue:174:41
let lastName = this.name.split(/[  ]/g)[0]
^

姓と名を分割したいけど半角スペースと全角スペースのどちらが区切り文字かわからないという場合のコード。

変なとこで空白使うなよ、って話でこれをなんとかしたいという話。


結論

半角スペースと全角スペースをそれぞれ文字コードで指定してやればよい。

// uフラグを指定

let lastName = this.name.split(/[\u{20}\u{3000}]/u)[0]

// uフラグなし
let lastName = this.name.split(/[\x20\u3000]/)[0]

半角スペースの文字コードが16進数で 20 で全角スペースの文字コードが16進数で 3000 となる。


正規表現での文字コードの指定

Javascriptの正規表現の中で文字コードを使う場合はバックスラッシュ文字 (\) を使った特殊文字を使う。

文字
意味

\xhh
 hh(2 桁の 16 進数)コードからなる文字列にマッチします。

\uhhhh
hhhh(4 桁の 16 進数)コードからなる文字列にマッチします。

\u{hhhh}
uフラグがセットされた時のみ Unicode 値 hhhh (16 進数) からなる文字列にマッチします。

引用元 - 特殊文字の使い方

正規表現の中では半角スペースを \x20、全角スペースを \u3000 として指定することができる。


文字コードの調べ方

文字コードを調べるには String.prototype.codePointAt() を使う。 codePointAt()で出力される値は10進数なので、正規表現の中で使う場合は16進数に変換する必要がある。

$ node

> ' '.codePointAt(0)
32
> ' '.codePointAt(0)
12288
// 16進数
> ' '.codePointAt(0).toString(16)
'20'
> ' '.codePointAt(0).toString(16)
'3000'


ひらがなの文字コード

ひらがなの文字コードはから始まりで終わるのでこの範囲を指定することでひらがなだけの文字列を正規表現で判定することができる。

それぞれの文字コードは String.prototype.codePointAt() で同様に調べるられる。

> ''.codePointAt(0)

12353
> ''.codePointAt(0)
12438
// 16進数
> ''.codePointAt(0).toString(16)
'3041'
> ''.codePointAt(0).toString(16)
'3096'

文字コードからString.fromCodePoint() を使って文字を出力することができる。

> for (i = 12352; i <= 12439; i++) {

... console.log(String.fromCodePoint(i))
... }




// 略



ひらがなのだけの文字列判定は以下のようにできる。

'にんいのひらがなもじれつ'.match(/[\u{3042}-\u{3096}]+/u)


カタカナの文字コード

同様にカタカナの文字コードは以下の範囲になる。

> ''.codePointAt(0)

12449
> ''.codePointAt(0)
12534
// 16進数
> ''.codePointAt(0).toString(16)
'30a1'
> ''.codePointAt(0).toString(16)
'30f6'

> for (var s='', i=12449; i<=12534; i++) { s=s+String.fromCodePoint(i) }
'ァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャ ヤュユョヨラリルレロヮワヰヱヲンヴヵヶ'

カタカナだけの文字列判定は以下のようになる。

> 'ニンイノカタカナ'.match(/[\u{30a1}-\u{30f6}]+/u)