速習ECMAScript2018を勉強する 正規表現編

正規表現

  • 正規表現については、正直苦手なのであんまり触れたくないんですが、だいぶ拡張されているみたいなので、拡張された部分の確認をしたいと思います。
  • 拡張されたというのは、後ろにつくgのようなoptionが増えたということです。
    • /[a-z]/g

ユニコード対応 uフラグ

  • node10 では、特にuフラグをつけなくても、 true になります。
  • しかし、unicode文字列を処理する場合、つけたほうがいいでしょうね。

const str = '叱られた'
console.log(/^.られた/u.test(str))

位置指定ができる yフラグ

  • これは、マッチング対象をずらしているイメージでしょうか。
  • 正規表現は基本パターンマッチングなのですが、位置指定ができると単純な指定は、これを使えばいいということになります。

const pattern = /HELLO/y
console.log('Flag: ', pattern.flags)  // 使われているフラグオプションの抽出
console.log(pattern.test('HELLO'))

pattern.lastIndex = 0;  // 添字は0からカウント
console.log(pattern.test('HELLO'))

pattern.lastIndex = 3;
console.log(pattern.test('sayHELLO'))
  • 0なら最初からマッチングで 3なら4文字目からマッチングされてます。

任意の文字を表す ドット記号の拡張 sフラグ

  • ドット記号 [.] は、任意の文字一文字を表しますが、制御記号等はマッチしなかったんですが、sフラグをつけるとそれらも含めてマッチします。
const pattern = /Hello.Takuma/s;
const string = 'Hello\nTakuma';
console.log(pattern.test(string)) 
  • これで、エスケープシーケンスが含まれていても、問題なくマッチングするようになりますね。

ひらがな、カタカナ等の抽出

  • ユニコード文字列には、分類コードが含まれていて、日本語関係では ひらがな・カタカナ・漢字・句読点等が分類できます。
  • Unicodeプロパティエスケープは、node9でエラーになったと思いますので、node10以上を使ってください。
  • ユニコードを扱うので、uフラグは必ず指定してください。
  • 否定はp を大文字に指定してください。
const string = '愛・おぼえていますか? フルイかな'
console.log('ひらがな', string.match(/\p{sc=Hiragana}/gu))
console.log('ひらがな以外', string.match(/\P{sc=Hiragana}/gu))
console.log('漢字', string.match(/\p{sc=Han}/gu))
console.log('漢字以外', string.match(/\P{sc=Han}/gu))

console.log('句読点', string.match(/\p{P}/gu))
  • 返り値は配列ですので、JSが得意なループで処理するかjoinで繋ぐかして処理できますね。
const string = '愛・おぼえていますか? フルイかな'
const result = string.match(/\p{sc=Hiragana}/gu);

console.log(result.join(''))
console.log(result.reduce((pre, correct) => pre + correct))

名前付きのキャプチャ

  • キャプチャのいうのは、マッチした文字列の抜き出しです。
  • 丸かっこ () を順番に抜き出せるものです。

  • 名前指定なし、キャプチャ

const message = 'tel:0120-33-1376';
const pattern = /(\d{4})-(\d{2})-(\d{4})/;
const result = message.match(pattern);
console.log('Result: ', result);

console.log('TEL: ', `${result[1]}-${result[2]}-${result[3]}`)
console.log(message.replace(pattern, '$1' + '$2' + '$3'))
node test.js
Result:  [ '0120-33-1376',
  '0120',
  '33',
  '1376',
  index: 4,
  input: 'tel:0120-33-1376',
  groups: undefined ]
TEL:  0120-33-1376
tel:0120331376
  • 丸かっこ内を配列で記憶しているので、指定して取り出せるものです。
  • これを順番の数字ではなく、文字列で指定できるものです。

  • 名前付きキャプチャ

    const message = 'tel:0120-33-1376';
    const pattern = /(?<First>\d{4})-(?<Second>\d{2})-(?<Third>\d{4})/;
    const result = message.match(pattern);
    console.log(result)
    console.log(result.groups.First)
    console.log(result.groups.Second)
    console.log(result.groups.Third)
node test.js
[ '0120-33-1376',
  '0120',
  '33',
  '1376',
  index: 4,
  input: 'tel:0120-33-1376',
  groups: { First: '0120', Second: '33', Third: '1376' } ]
0120
33
1376
  • $数字の代わりに、名前で抜き出し文字を指定できるようになります。
  • 複雑になる場合は、名前で抜き出したほうが順番を確認する必要がなくなるので、いいかもしれませんね。