正規表現を引数にとれるメソッド
String.prototypeには正規表現を引数にとれるメソッドがいくつか存在します。
正規表現を引数に使用することで、さまざまなパターンを柔軟に設定することができるようになります。
この記事では正規表現を使用できるStringメソッドについて簡単にまとめてみます。
replace()
replace()は第1引数に指定した正規表現にマッチする箇所を、第2引数で指定した文字列で置換できます。
const regex = /\d+/
'a1b2c3'.replace(regex,'foo') // "afoob2c3"
パターンにgフラグを指定すれば、マッチしたすべての文字列を置換することもできます。
const regex = /\d+/g
'a1b2c3'.replace(regex,'foo') // "afoobfoocfoo"
replaceAll()
また、マッチ箇所全てを置換するためのメソッドとしてreplaceAllというものも用意されています。
replaceAllを使用する場合にも正規表現にgフラグがないとエラーとなります。
replaceでもgフラグがあれば全置換となりますが、replaceAllの方が対象全てを置換することが明確ですね。
search()
search()は最初にマッチした文字の位置を返します。
文字位置の先頭は0から数えます。
const regex = /\d+/
'foo1bar2'.search(regex)// 3
split()
split()は引数で指定した区切り文字によって、文字列を分割した配列を返します。
この区切り文字は正規表現によって指定することが可能です。
// 区切り文字を複数指定した例
const regex = /[,.]/
const fish = "octopus,squid.tuna,salmon.".split(regex)
//["octopus", "squid", "tuna", "salmon", ""]
引数に指定した正規表現がキャプチャグループをもつときには、返り値の配列にキャプチャグループにマッチした文字列も含まれます。
const regex = /([,.])/
const fish = "octopus,squid.tuna,salmon.".split(regex)
//["octopus", ",", "squid", ".", "tuna", ",", "salmon", ".", ""]
サロゲートペア文字の分割
split()を使用すると1文字ずつに分割することもできます。
'abc'.split('') //["a", "b", "c"]
しかし、split('')はコードユニット単位(16bit単位)で文字を分割するため、サロゲートペア文字などの複数のコードユニットで構成される文字をうまく分割することができません。
'a🧑c'.split('') //["a", "�", "�", "c"]
このようなケースでは、Array.fromやスプレッド構文[...]を使用することでうまく分割できるようになります1。
Array.from('a🧑c') // ["a", "🧑", "c"]
[...'a🧑c'] // ["a", "🧑", "c"]
splitにuフラグの正規表現を渡すことによっても分割することができ、16bit単位ではなくUnicode文字単位でのマッチをさせられるようにできます。
const regex = /(?=[\s\S])/u
'a🧑c'.split(regex) //["a", "🧑", "c"]
上の例の[\s\S]は\s(空白文字)と\S(空白文字以外)のいずれかの文字を文字クラス[\s\S]で表しており、これはすべての文字にあたります。
また、先読み言明(?=)によって、後ろに文字がある場合にマッチするように指定しています。
//uのようにして空文字を指定することはできないため、間接的な方法を取る必要があります。
先読み言明については以下でも扱っています。
match()
match()はマッチした箇所を配列で返します。
const pattern = /\d+/;
const text = 'a123b2c3'
text.match(pattern) //["123"]
gを設定しないときの挙動
gフラグが設定されていないときにはマッチした箇所に関するキャプチャグループの文字列を配列に含めて返します。
const regex = /(abc){3}/ //"abc"を3回繰り返すパターン
"abcabcabc".match(regex) // ["abcabcabc", "abc"]
キャプチャグループを含めたくない場合には、パターン内のグループを(と)で囲むのではなく、(?:と)で囲みます。
const regex = /(?:abc){3}/
"abcabcabc".match(regex) // ["abcabcabc"]
また、gフラグが設定されていないときの返り値の配列には、配列要素の他にいくつかのオブジェクトプロパティが含まれます。
indexやinput, groupsなどの正規表現や呼び出し元の文字列に関する情報が取得できます。
inputプロパティにはmatch()の呼び出し元の文字列が格納されています。
indexプロパティにはマッチ箇所の始めの位置が格納されます。
また、groupsプロパティにはキャプチャグループが格納されます。
const regex = /(?<abc_group>abc){3}/
const match = "abcabcabc".match(regex)
match?.input // "abcabcabc"
match?.index // 0
match?.groups //{"abc_group": "abc"}
-
🧑🧑🧒など複数の絵文字で構成されている絵文字はこの方法でも見た目通り(書記素クラスタ単位)には分割されません。 ↩