LoginSignup
6

🔰【正規表現】前方一致、前方不一致、後方一致、後方不一致

Last updated at Posted at 2020-08-11

正規表現で次のようなパターンの文字列を検索したり、置換したりしたいときのメモです。

💡 胡瓜の絵文字はプレースホルダです
本記事内のサンプルコードに含まれる「🥒」は、任意の文字列に置き換えてください。

💡 このサンプルは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

📝 参考文献

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6