Java 一个正则表达式来匹配后面没有某个其他子字符串的子字符串

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2631010/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 10:05:49  来源:igfitidea点击:

A regex to match a substring that isn't followed by a certain other substring

javaregexclojure

提问by Rayne

I need a regex that will match blahfooblahbut not blahfoobarblah

我需要一个匹配blahfooblah但不匹配的正则表达式blahfoobarblah

I want it to match only foo and everything around foo, as long as it isn't followed by bar.

我希望它只匹配 foo 和 foo 周围的所有内容,只要它后面没有 bar。

I tried using this: foo.*(?<!bar)which is fairly close, but it matches blahfoobarblah. The negative look behind needs to match anything and not just bar.

我尝试使用这个:foo.*(?<!bar)这是相当接近的,但它匹配blahfoobarblah. 背后的负面外观需要匹配任何东西,而不仅仅是酒吧。

The specific language I'm using is Clojure which uses Java regexes under the hood.

我使用的特定语言是 Clojure,它在底层使用 Java 正则表达式。

EDIT: More specifically, I also need it to pass blahfooblahfoobarblahbut not blahfoobarblahblah.

编辑:更具体地说,我也需要它通过blahfooblahfoobarblah但不是blahfoobarblahblah.

采纳答案by ma?ek

Try:

尝试:

/(?!.*bar)(?=.*foo)^(\w+)$/

Tests:

测试:

blahfooblah            # pass
blahfooblahbarfail     # fail
somethingfoo           # pass
shouldbarfooshouldfail # fail
barfoofail             # fail

Regular expression explanation

正则表达式解释

NODE                     EXPLANATION
--------------------------------------------------------------------------------
  (?!                      look ahead to see if there is not:
--------------------------------------------------------------------------------
    .*                       any character except \n (0 or more times
                             (matching the most amount possible))
--------------------------------------------------------------------------------
    bar                      'bar'
--------------------------------------------------------------------------------
  )                        end of look-ahead
--------------------------------------------------------------------------------
  (?=                      look ahead to see if there is:
--------------------------------------------------------------------------------
    .*                       any character except \n (0 or more times
                             (matching the most amount possible))
--------------------------------------------------------------------------------
    foo                      'foo'
--------------------------------------------------------------------------------
  )                        end of look-ahead
--------------------------------------------------------------------------------
  ^                        the beginning of the string
--------------------------------------------------------------------------------
  (                        group and capture to :
--------------------------------------------------------------------------------
    \w+                      word characters (a-z, A-Z, 0-9, _) (1 or
                             more times (matching the most amount
                             possible))
--------------------------------------------------------------------------------
  )                        end of 
--------------------------------------------------------------------------------
  $                        before an optional \n, and the end of the
                           string

Other regex

其他正则表达式

If you only want to exclude barwhen it is directly after foo, you can use

如果您只想在bar直接在 之后排除,则foo可以使用

/(?!.*foobar)(?=.*foo)^(\w+)$/


Edit

编辑

You made an update to your question to make it specific.

您对问题进行了更新以使其具体。

/(?=.*foo(?!bar))^(\w+)$/

New tests

新测试

fooshouldbarpass               # pass
butnotfoobarfail               # fail
fooshouldpassevenwithfoobar    # pass
nofuuhere                      # fail

New explanation

新解释

(?=.*foo(?!bar))ensures a foois found but is not followed directly bar

(?=.*foo(?!bar))确保foo找到 a 但不直接跟随bar

回答by Audie

Use a negative look ahead instead:

使用负面展望代替:

\s*(?!\w*(bar)\w*)\w*(foo)\w*\s*

This worked for me, hope it helps. Good luck!

这对我有用,希望它有所帮助。祝你好运!

回答by stevemegson

To match a foofollowing by something that doesn't start with bar, try

要匹配foo不以 开头的内容bar,请尝试

foo(?!bar)

Your version with negative lookbehind is effectively "match a foofollowed by something that doesn't end in bar". The .*matches all of barblah, and the (?<!bar)looks back at lahand checks that it doesn't match bar, which it doesn't, so the whole pattern matches.

您的负面回顾版本实际上是“匹配 afoo后跟不以bar”结尾的内容。本.*场比赛所有的barblah,和(?<!bar)长相背部lah,并检查不匹配bar,它没有,所以整个模式匹配。

回答by dawg

Your specific match request can be matched by:

您的特定匹配请求可以通过以下方式匹配:

\w+foo(?!bar)\w+

This will match blahfooblahfoobarblahbut not blahfoobarblahblah.

这将匹配blahfooblahfoobarblah但不匹配blahfoobarblahblah

The problem with your regex of foo.*(?<!bar)is the .*after foo. It matches as many of any characters including characters after bar.

您的正则表达式的问题foo.*(?<!bar).*after foo。它匹配尽可能多的任何字符,包括bar.

回答by ma?ek

You wrote a comment suggesting you like this to work matching all words in a string rather than the whole string itself.

您写了一条评论,建议您喜欢这样匹配字符串中的所有单词而不是整个字符串本身。

Rather than mashing all of this in a comment, I'm posting it as a new answer.

我没有在评论中混合所有这些,而是​​将其作为新答案发布。

New Regex

新正则表达式

/(?=\w*foo(?!bar))(\w+)/

Sample text

示例文本

foowithbar fooevenwithfoobar notfoobar foohere notfoobarhere butfooisokherebar notfoobarhere andnofuu needsfoo

foowithbar fooevenwithfoobar notfoobar foohere notfoobarhere butfooisokherebar notfoobarhere andnofuu requiresfoo

Matches

火柴

foowithbar fooevenwithfoobar foohere butfooisokherebar needsfoo

foowithbar fooevenwithfoobar foohere butfooisokherebar需要foo