正規表現の一部を一致させるが、キャプチャしない方法は?


209

文字列のリストがあります。それらのいくつかはの形式123-...456です。可変部分 "..."は次のとおりです。

  • 文字列 "apple"とそれに続くハイフン 123-apple-456
  • 文字列 "banana"とそれに続くハイフン 123-banana-456
  • 空白の文字列、たとえば123-456(ハイフンは1つしかありません)

「apple」または「banana」以外の単語は無効です。

この3つのケースでは、それぞれ「apple」、「banana」、「」を照合します。ハイフンはキャプチャしたくありません、常に一致させたいことに注意してください。文字列が123-...456上記の形式でない場合は、まったく一致しません。

これを行うには正規表現をどのように記述すればよいですか?先読み、後読み、先読み、非キャプチャグループを許可するフレーバーがあると仮定します。


ここで重要なのは、「apple」または「banana」のいずれかがある場合、末尾のハイフンも必要ですが、一致させたくないということです。また、空白文字列を照合する場合は、末尾にハイフンを付けないでください。この主張をカプセル化する正規表現は正しいものだと思います。


ハイフン以外のすべてに一致させたいですか?
BrunoLM

回答:


285

何かをキャプチャしない唯一の方法は、アラウンドアサーションを使用することです。

(?<=123-)((apple|banana)(?=-456)|(?=456))

そのためにもと非キャプチャグループ(?:…)全体の正規表現は、そのマッチした内容をキャプチャします。しかし、この正規表現は一致するappleか、bananaそれがが先行だ場合123-と続く-456、あるいはそれがが先行していますならば、それは空の文字列に一致123-し、続きます456

|Lookaround  |    Name      |        What it Does                       |
-----------------------------------------------------------------------
|(?=foo)     |   Lookahead  | Asserts that what immediately FOLLOWS the |
|            |              |  current position in the string is foo    |
-------------------------------------------------------------------------
|(?<=foo)    |   Lookbehind | Asserts that what immediately PRECEDES the|
|            |              |  current position in the string is foo    |
-------------------------------------------------------------------------
|(?!foo)     |   Negative   | Asserts that what immediately FOLLOWS the |
|            |   Lookahead  |  current position in the string is NOT foo|
-------------------------------------------------------------------------
|(?<!foo)    |   Negative   | Asserts that what immediately PRECEDES the|
|            |   Lookbehind |  current position in the string is NOT foo|
-------------------------------------------------------------------------

1
+1 —この場合、グループ0ではなくグループ1を使用することで回避できますが、これは優れた(そして微妙な!)違いです。
Ben Blank

@Ben Blank:「一致」と「キャプチャ」がどのように解釈されるかによって、確実に異なります。
ガンボ

8
、JavaScriptでサポートされていませんイェーイ!JSフレンドリーな方法があればいいのですが、悪くはありません。
+ 0.5

見回すアサーションが大好きです!これらはRubyでも動作します。
Rots

完璧なソリューション、私はこれを愛する
TRANクアンヒェップ

15

更新:GermánRodríguezHerreraに感謝!

JavaScriptで試してください: /123-(apple(?=-)|banana(?=-)|(?!-))-?456/

結果はグループ1であることに注意してください

Debuggexデモ


8

試してください:

123-(?:(apple|banana|)-|)456

これは、、、または空の文字列に一致しapplebananaその後に0または1のハイフンが続きます。捕獲グループが必要ないのは間違いでした。愚かな私。


たとえば "123-coconut-456"と一致するため、これは正しくありません。
David Stone、

もっと一般的なものにしたいと思っていました...修正されました。
Thomas

5

私は答えの1つを変更しました(@ op1ekunによる):

123-(apple(?=-)|banana(?=-)|(?!-))-?456

その理由は、@ op1ekunからの回答もに一致し"123-apple456"、appleの後にハイフンがない場合です。


3

これを試して:

/\d{3}-(?:(apple|banana)-)?\d{3}/

1
たとえば "123-coconut-456"と一致するため、これは正しくありません。
David Stone、

@david:「バナナ」の例とどう違うのですか?
SilentGhost

@SilentGhost:or または "" のみをキャプチャしたい。私が述べたように、他のすべての値は無効です。applebanana
David Stone、

申し訳ありませんが
slosd

1
この例が示すのは、先読みと後読みを使用せずに非キャプチャグループを作成できることです。
Vince Panuccio

0

\Kマッチに数値ブロックが含まれないようにマッチ位置をリセットするために使用する@Gumboによる式のバリエーション。PCRE正規表現のフレーバーで使用できます。

123-\K(?:(?:apple|banana)(?=-456)|456\K)

一致:

Match 1  apple
Match 2  banana
Match 3

-3

はるかに単純な(Pythonで動作する)は'123-(apple|banana)-?456'です。


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