正規表現は正確にnまたはm回


105

次の正規表現を考えてみます。ここで、X任意の正規表現です。

X{n}|X{m}

この正規表現は、正確に、または何度もX発生する nどうかをテストしmます。

発生をX正確にnまたはm時間でテストできる正規表現数量詞はありますか?


いいえ。の2つのオカレンスXは、一般的なmで得られる最高のものですn
John Dvorak

これが私の問題である場合、私は正規表現の後方参照を試し、から始めます(X)\1{n-1}(?:\1{m-n-1})。私はこれXが少なくとも1回は一致することを知っていますが、最初にこの簡単なことを試してから、の代わりに先読みまたは後読みを使用して調整し(X)ます。
nalply

回答:


91

「正確にmまたはn回」を意味する単一の数量詞はありません。あなたのやり方は問題ありません。

別の方法は次のとおりです。

X{m}(X{k})?

ここm < nk、はの値ですn-m


67

量指定子の完全なリストは次のとおりです(http://www.regular-expressions.info/reference.htmlを参照):

  • ???-0または1回の出現(??怠惰、?貪欲)
  • **?-任意の数の発生
  • ++?-少なくとも1つの発生
  • {n}-正確にn発生
  • {n,m}- nm発生箇所、包括的
  • {n,m}?-発生nするm、怠惰な
  • {n,}{n,}?-少なくともn発生

「正確にNまたはM」を取得するには、m、nが特別でない限り、定量化された正規表現を2回記述する必要があります。

  • X{n,m} もし m = n+1
  • (?:X{n}){1,2} もし m = 2n
  • ...

1
?:ifのm = 2n例でなぜ必要なのですか?私にとっては、それなしで問題なく動作するようです。
erb 2015年

7
@erb省略した場合?:、グループはキャプチャグループになります。正規表現エンジンが必要としないものを記憶することは別として、このグループの後にキャプチャグループがある場合、それらのIDは変更されます。置換に正規表現を使用する場合は、置換を調整する必要があります。
John Dvorak


3

TLDR; (?<=[^x]|^)(x{n}|x{m})(?:[^x]|$)

「xn回」または「xm回」が必要なようですが、正規表現への直訳は次のようになる(x{n}|x{m}). と思いますhttps://regex101.com/r/vH7yL5/1

または、mを超える「x」のシーケンスを使用できる場合(m> nと想定)、「「x」なし」と「xなし」を追加して、次のように変換[^x](x{n}|x{m})[^x]できます。 「x」の後ろと後ろには常にキャラクターがいると仮定します。あなたがここで見ることができるように:https : //regex101.com/r/bB2vH2/1

これをに変更して(?:[^x]|^)(x{n}|x{m})(?:[^x]|$)、「 'x'がないか、次の行の先頭に続く」、「 'x'がない、または行の終わりが続く」に変換できます。しかし、それでも、https//regex101.com/r/を見るとわかるように、2つのシーケンスの間に文字が1つだけある場合は一致しません(最初の一致の後には文字が必要で、2番目の文字はその前にあるため)。 oC5oJ4 / 1

最後に、1文字の遠い一致に一致させるには、「後の「x」なし」に前向きの肯定(?=)を追加するか、「前の「x」前」に後ろ向きの肯定(?<=)を追加します。このように:https : //regex101.com/r/mC4uX3/1

(?<=[^x]|^)(x{n}|x{m})(?:[^x]|$)

このようにして、必要な「x」の正確な数のみを照合します。


1

Enhardenedの回答を見ると、最後から2番目の表現は、間に1文字しかないシーケンスとは一致しないと述べています。先読み/後読みを使用せずにこれを修正する簡単な方法があります。これは、開始/終了文字を境界文字に置き換えることです。これにより、開始/終了を含む単語の境界と照合できます。したがって、適切な式は次のようになります。

(?:[^x]|\b)(x{n}|x{m})(?:[^x]|\b)

あなたがここで見ることができるように:https : //regex101.com/r/oC5oJ4/2


1
かっこいい、正規表現が境界を処理する方法に慣れていなかった。この方法の唯一の問題は、非標準の境界を使用している場合です。外観を見る:regex101.com/r/j0nkeo/1およびregex101.com/r/4Ix7Dr/1
Enhardened

1
@Enhardened-それは良い点です。重複する複数の一致するグループの問題のようです。これは、ルックビハインドを使用する必要がある状況です。
rozza2058

1

非常に古い投稿ですが、役立つかもしれないsthを寄稿したいと思います。私は質問で述べたとおりに試してみましたが、うまくいきますが、落とし穴があります。数量の順序が重要です。このことを考慮:

#[a-f0-9]{6}|#[a-f0-9]{3}

これにより、16進数のカラーコード(3桁または6桁の長さ)がすべて検出されます。でもこのようにひっくり返すと

#[a-f0-9]{3}|#[a-f0-9]{6}

3桁の数字、または6桁の数字の最初の3桁のみが検索されます。これは理にかなっており、正規表現のプロはこれをすぐに見つけるかもしれませんが、多くの人にとってこれは独特の振る舞いかもしれません。順序に関係なくこのトラップを回避できるいくつかの高度なRegex機能がありますが、すべてのユーザーがRegexパターンに精通しているわけではありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.