正規表現で次のようなパターンの文字列を検索したり、置換したりしたいときのメモです。
💡 胡瓜の絵文字はプレースホルダです
本記事内のサンプルコードに含まれる「🥒」は、任意の文字列に置き換えてください。
💡 このサンプルはJavaScriptで描かれています
JavaScriptでは、正規表現を表すためにスラッシュデリミタで囲む必要があります。
const 正規表現ではない = '^hoge$';
const 正規表現 = /^hoge$/;
1. 文字列全体について
-
^🥒
: 特定の文字で始まるパターン -
^(?!🥒)
: 特定の文字で始まらないパターン -
🥒$
: 特定の文字で終わるパターン -
^(?!.*🥒$).*
: 特定の文字で終わらないパターン
💡 正規表現フラグ
JavaScriptでは、正規表現フラグという概念があります。
大文字小文字を区別しない、文全体ではなく行ごとに検査する、などです。
// hoge という文字で始まり、終わっているかを確認する
const 改行ごとにチェックする = /^hoge$/m;
const 文字列全体をチェックする = /^hoge$/;
const 文字列 = `hoge
piyo
ponyo`;
改行ごとにチェックする.test(文字列); // -> true
文字列全体をチェックする.test(文字列); // -> false
See Also: 正規表現 - JavaScript | MDN #フラグを用いた高度な検索
前方一致:特定の文字で始まっていることを確認したい
正規表現
const regExp = /^🥒/
// hogeで始まってるかどうか
/^hoge/.test('hoge文字列') // -> true
/^hoge/.test('文字列') // -> false
実行例
// 文字列の先頭の「abc」を★にしたい
'abcdef'.replace(/^abc/, '★') // -> ★def
'abcDEF'.replace(/^abc/, '★') // -> ★DEF
'ABCdef'.replace(/^abc/, '★') // -> ABCdef
'_abcdef'.replace(/^abc/, '★') // -> _acbdef
前方不一致:特定の文字で始まっていないことを確認したい
正規表現
const regExp = /^(?!🥒)./
// hogeで始まってないかどうか
/^(?!hoge)./.test('文字列') // -> true
/^(?!hoge)./.test('hoge文字列') // -> false
実行例
// 「abc」で始まっていない文字列の最初の1文字を★にしたい
'abcdef'.replace(/^(?!abc)./, '★') // -> abcdef
'abcDEF'.replace(/^(?!abc)./, '★') // -> abcDEF
'ABCdef'.replace(/^(?!abc)./, '★') // -> ★BCdef
'_abcdef'.replace(/^(?!abc)./, '★') // -> ★abcdef
後方一致:特定の文字で終わっていることを確認したい
正規表現
const regExp = /🥒$/
// hogeで終わってるかどうか
/hoge$/.test('文字列hoge') // true
/hoge$/.test('文字列') // false
実行例
// 文字列の最後の「def」を★にしたい
'abcdef'.replace(/def$/, '★') // -> abc★
'abcDEF'.replace(/def$/, '★') // -> abcDEF
'ABCdef'.replace(/def$/, '★') // -> ABC★
'_abcdef'.replace(/def$/, '★') // -> _abc★
後方不一致:特定の文字で終わっていないことを確認したい
単一の文字で終わっていないことを確認するケースを除いて、基本的には後方一致($
)で検査して、「一致していない」ことを確認したほうがよい。
正規表現
const regExp = /^(.*)([^🥒])$/
// hogeの4文字いずれかで終わっていないかどうか
/^(.*)([^hoge])$/.test('文字列') // true
/^(.*)([^hoge])$/.test('文字列hoge') // false
/^(.*)([^hoge])$/.test('文字列hego') // false
/^(.*)([^hoge])$/.test('文字列geo') // false
/^(.*)([^hoge])$/.test('文字列o') // false
実行例
// 「d」「e」「f」で終わっていない文字列の最後の1文字を★にしたい
'abcdef'.replace(/^(.*)([^def])$/, '$1★') // -> abcdef
'abcDEF'.replace(/^(.*)([^def])$/, '$1★') // -> abcDE★
'ABCdef'.replace(/^(.*)([^def])$/, '$1★') // -> ABCdef
'_abcdef'.replace(/^(.*)([^def])$/, '$1★') // -> _abcdef
'abcfed'.replace(/^(.*)([^def])$/, '$1★') // -> abcfed
'deABCf'.replace(/^(.*)([^def])$/, '$1★') // -> deABCf
'_abdfce'.replace(/^(.*)([^def])$/, '$1★') // -> _abdfce
2. 文中について
-
(?<=🥒)
: 特定の文字から続くパターン -
(?<!🥒)
: 特定の文字から続かないパターン -
(?=🥒)
: 特定の文字が後に続くパターン -
(?!🥒)
: 特定の文字が後に続かないパターン
丸各個についての注意点
前方一致、後方一致で登場するパーレン(丸括弧)はキャプチャグループとして機能しません。
パーレンの中身が参照できる例
// 文字列の`$1`で参照できる状態
'abcdef'.replace(/(.*?)def/, '$1'); // -> 'abc'
// 第2引数`p1`で参照できる状態
'abcdef'.replace(/(.*?)def/, (_, p1) => {
console.log(p1); // > 'abc'
return p1;
}); // -> 'abc'
パーレンの中身が参照できない例
'abcdef'.replace(/(?<=abc)def/, '$1'); // -> 'abc$1'
前方一致:特定の条件の後に続く文字列を探索したい
正規表現
const regExp = /(?<=🥒)/
実行例
// abcに続く「def」を★にしたい
'_abcdef'.replace(/(?<=abc)def/, '★') // -> _abc★
'_abcDEF'.replace(/(?<=abc)def/, '★') // -> _abcDEF
'_ABCdef'.replace(/(?<=abc)def/, '★') // -> _ABCdef
'_123def'.replace(/(?<=abc)def/, '★') // -> _123def
前方不一致:特定の条件以外の後に続く文字列を探索したい
正規表現
const regExp = /(?<!🥒)/
実行例
// abc以外の文字列に続く「def」を★にしたい
'_abcdef'.replace(/(?<!abc)def/, '★') // -> _abcdef
'_abcDEF'.replace(/(?<!abc)def/, '★') // -> _abcDEF
'_ABCdef'.replace(/(?<!abc)def/, '★') // -> _ABC★
'_123def'.replace(/(?<!abc)def/, '★') // -> _123★
後方一致:特定の条件が後に続く文字列を探索したい
正規表現
const regExp = /(?=🥒)/
実行例
// defが後に続く「abc」を★にしたい
'_abcdef'.replace(/abc(?=def)/, '★') // -> _★def
'_abcDEF'.replace(/abc(?=def)/, '★') // -> _abcDEF
'_ABCdef'.replace(/abc(?=def)/, '★') // -> _ABCdef
'_abc123'.replace(/abc(?=def)/, '★') // -> _abc123
後方不一致:特定の条件が後に続かない文字列を探索したい
正規表現
const regExp = /(?!🥒)/
実行例
// defが後に続かない「abc」を★にしたい
'_abcdef'.replace(/abc(?!def)/, '★') // -> _abcdef
'_abcDEF'.replace(/abc(?!def)/, '★') // -> _★DEF
'_ABCdef'.replace(/abc(?!def)/, '★') // -> _ABCdef
'_abc123'.replace(/abc(?!def)/, '★') // -> _★123