正規表現の角括弧と括弧の違いは何ですか?


101

JavaScriptで使用するために作成した正規表現は次のとおりです。

var reg_num = /^(7|8|9)\d{9}$/

これは私のチームメンバーから提案された別の1つです。

var reg_num = /^[7|8|9][\d]{9}$/

ルールは電話番号を検証することです:

  • それはたった10の数字であるべきです。
  • 最初の数は、7、8、または9のいずれかになるはずです。

回答:


124

これらの正規表現は同等です(照合の目的で)。

  • /^(7|8|9)\d{9}$/
  • /^[789]\d{9}$/
  • /^[7-9]\d{9}$/

説明:

  • (a|b|c)は正規表現「OR」であり、「aまたはbまたはc」を意味しますが、ORに必要な括弧の存在も数字をキャプチャします。厳密に同等にするには(?:7|8|9)、それをキャプチャーグループにするようにコーディングします。

  • [abc]「a、b、cのいずれかの文字」を意味する「文字クラス」です(文字クラスには範囲を使用できます。例:[a-d]= [abcd]

これらの正規表現が類似している理由は、文字クラスが "or"の省略形であるためです(ただし、単一文字のみ)。代替(abc|def)では、文字クラスに変換されないようなこともできます。


30
(7|8|9)[789]は同等ではありません。最初のものがキャプチャであり、後者はキャプチャではありません。(?:7|8|9)一方、同等です(もちろんそれを知っていると思います...)。
hochl 2012年

次の正規表現が表示されます[<<|>>|\]\]|\[\[]。コンテキストが原因で、正規表現が<<or >>または[[or に一致しようとしていることを知ってい]]ます。しかし、あなたが言ったことから、それは<or >または[orに一致するはず]です。|between を使用する場合[]、ブラケットの動作は異なりますか?
Daniel Kaplan

1
@DanielKaplanは、パイプ文字自体と一致させたい場合を除き|、文字クラス内では使用しません[...]。また、文字クラスで文字を複製しても効果はありません。文字クラスは文字のリストであり、そのうちの1つと完全に一致します。私の推測では、あなたが希望されるグループ:通常の丸括弧を使用して、(<<|>>|\]\]|\[\[)
ボヘミアン

57

あなたのチームのアドバイスは、行われた間違いを除いて、ほぼ正しいです。理由がわかれば、決して忘れません。この間違いを見てください。

/^(7|8|9)\d{9}$/

これは何をしますか:

  • ^$アンカーされた一致を示し、これらのアンカー間のサブパターンが完全な一致であることを表明します。文字列は、サブパターンがセクションだけでなく、その全体と一致する場合にのみ一致します。
  • () を示します キャプチャグループをます。
  • 7|8|9いずれかのマッチング表し78または9。それはでこれを行い交替パイプ演算子は何である、|交番の間で交互に-ありません。これは、代替案間のバックトラックです。最初の代替案が一致しない場合、エンジンは、代替案の一致中にポインタの位置が移動する前に戻り、次の代替案の一致を継続する必要があります。一方、文字クラスは順次進むことができます。最適化を無効にした正規表現エンジンでこの一致を確認します。
Pattern: (r|f)at
Match string: carat

交互

Pattern: [rf]at
Match string: carat

クラス

  • \d{9}9桁と一致します。\dあらゆる数字に一致する短縮形のメタ文字です。
/^[7|8|9][\d]{9}$/

それが何をするか見てください:

  • ^$にもアンカーの一致を示しています。
  • [7|8|9]文字クラスです。リストから任意の文字7|8|、または9ので、一致させることができ|、誤っに追加されました。これはバックトラックなしで一致します。
  • [\d]はメタキャラクターに生息するキャラクタークラスです\d。ちなみに、抽象化の層は一致を遅くする可能性があるため、文字クラスと単一のメタ文字の使用の組み合わせは悪い考えですが、これは実装の詳細にすぎず、いくつかの正規表現実装にのみ適用されます。JavaScriptは1つではありませんが、サブパターンを少し長くします。
  • {9} 以前の単一の構成が合計9回繰り返されていることを示します。

最適な正規表現は/^[789]\d{9}$//^(7|8|9)\d{9}$/不必要にキャプチャする、ほとんどの正規表現の実装でパフォーマンスが低下します(質問varがコードでキーワードを使用していることを考えると、たまたまこれはJavaScriptです)。の用法pregマッチングのためにPCREで実行すると、バックトラッキングの欠如が最適化されますが、PHPにはないため[]、代替の代わりにクラスを使用する|と、マッチがバックトラックせず、一致と失敗の両方が発生するため、パフォーマンスが向上します。以前の正規表現。


6
ちょうど興味があるのですが、そのスクリーンショットはどのプログラムからのものですか?
Mr Mystery Guest

12

最初の2つの例は、何かで置き換えると非常に異なる動作をします。これに一致する場合:

str = str.replace(/^(7|8|9)/ig,''); 

7または8または9を空の文字列に置き換えます。

これにマッチしたら

str = str.replace(/^[7|8|9]/ig,''); 

7またはまたは8または9バーを交換します!!!! 空の文字列によって。

私はこれを難しい方法で見つけました。


6
SOへようこそ!置き換えるか一致させるかは、明らかに間違っています。多くの人々がその間違いを犯し、彼らの入力文字列にはたまたまパイプ(|)が含まれることはないため、彼らは通常、何年もの間、時にはそれを回避します。
アランムーア
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.