意外と知られていないJavaScript replaceの$&や$`などの使用方法

replaceとは

文字列の1つまたはすべてを置換するメソッド。

例えば 'apple pie'.replace('pie', 'pen') のように記述すると文字列のpieがpenに置換されて「apple pen」になる。

'apple pie'.replace('pie', 'pen')
// 'apple pen'

1つまたはすべてを置換

前述の書き方だと最初にマッチした1つしか置換できない。

すべて置換するには正規表現を使用して /pie/g と記述する必要がある。

let str = 'apple pie and meat pie'
str.replace('pie', 'pen')
// apple pen and meat pie

let str = 'apple pie and meat pie'
str.replace(/pie/g, 'pen')
// apple pen and meat pen

コールバック関数で置換処理

「7/23/2021」を「2021年7月23日」に置換したい場合は正規表現を使用して以下のように書かれることが多い。

const dateEN = '7/23/2021'
const dateJP = dateEN.replace(/(\d{1,2})\/(\d{1,2})\/(\d{4})/g, '$3年$1月$2日')
console.log(dateJP)
// 2021年7月23日

ただし、括弧でのキャプチャが多いと$nで指定している番号が間違っていても気づきにくいという欠点がある。

そのような場合はコールバック関数で置換処理を行うとコードがわかりやすくなる。

const dateEN = '7/23/2021'
const dateJP = dateEN.replace(/(\d{1,2})\/(\d{1,2})\/(\d{4})/g, (all, month, date, year) => {
  return `${year}年${month}月${date}日`
})
console.log(dateJP)
// 2021年7月23日

正規表現の先読みや後読みも使用可能

replaceは正規表現の肯定(否定)先読みや後読みが使用できるため、例えば「ヒロ」という文字列の直前に「☆」を入れたい場合、先読みや後読みが使用しないと…

let str = 'つのだひろ'
str.replace(/ひろ/g, '☆ひろ')
// つのだ☆ひろ

となるが、先読みや後読みを使用すると…

let str = 'つのだひろ'
str.replace(/(?=ひろ)/g, '☆')
// つのだ☆ひろ

となり、結果は同じだがreplace内の「ひろ」の指定は1つで済む。

$&でマッチした部分文字列を挿入

「$&」を使用するとマッチした部分文字列を挿入できる。

これを使用せずに例えば以下のような「ひろ」の前に「つのだ」がある文字列の置換の場合…

let str = 'つのだひろとやまだひろ'
str.replace(/(つのだ)(?=ひろ)/g, '$1☆')
// つのだ☆ひろとやまだひろ

…となるが、$&を使用すれば括弧でキャプチャしなくてもマッチした「つのだ」の部分が$&で挿入できるため、括弧の使用を少なくできる。

let str = 'つのだひろとやまだひろ'
str.replace(/つのだ(?=ひろ)/g, '$&☆')
// つのだ☆ひろとやまだひろ

$`で直前の文字列の部分を挿入

「$`」でマッチした文字列の部分を挿入できる。

let str = 'むかしあるところに'
str.replace(/あるところに/g, '$`$&')
// むかしむかしあるところに

$'で直後の文字列の部分を挿入

「$'」でマッチした直後の文字列の部分を挿入できる。

let str = '名前はシャン'
str.replace(/名前は/g, "$&$'")
// 名前はシャンシャン