RegEx:查找模式但排除单词

5

我想找出除特定单词外的所有连接字。例如:

0827banana82/+wine22green-729

greenwine 应该匹配,但不应该匹配 banana

我尝试使用负向先行断言的正则表达式:

(?!banana)([a-zA-Z]+)

但它只排除了 banana 的第一个字母,因为 anana 仍然与第二个模式匹配。我不知道如何解决这个问题。

6个回答

3
你可以在正则表达式中添加负回顾后断言来实现此功能:
(?!banana)(?<![a-zA-Z])[a-zA-Z]+

正则表达式演示

正则表达式细节:

  • (?!banana):负向前瞻,断言当前位置之后没有字符串banana
  • (?<![a-zA-Z]):负向后顾,断言当前位置之前没有字母
  • [a-zA-Z]+:匹配 1 个或多个字母

提示:如果您想允许类似 bananas 的单词,则可以使用:

(?!banana(?![a-zA-Z]))(?<![a-zA-Z])[a-zA-Z]+

2
好的,您可以使用这个:

嗯,您可以使用这个:

(banana)|([a-zA-Z]+)

这将在第一组中捕获香蕉,并在第二组中捕获所有其他单词。


你也可以使用单个捕获组 banana|([a-zA-Z]+) - The fourth bird
1
请注意,这将使像“香蕉”这样的单词变为相反意思。 - JvdV

2

我觉得,假设你确实想匹配像“香蕉”这样的单词:

(\b|\d)(?:banana|([a-zA-Z]+))(?1)

您的匹配结果在第2组,可以查看在线演示

  • (\b|\d) - 第1个捕获组用于匹配单词边界或数字。
  • (?:banana|([a-zA-Z]+)) - 非捕获组,要么完全匹配"banana",要么是第2个捕获组中由1个或多个字母组成的字符串。
  • (?1) - 重复第1个捕获组的子模式。

编辑: 如果不支持反向引用,可以尝试

(?:\b|\d)(?:banana|([a-zA-Z]+))(?:\b|\d)

或者,使用环视:

(?i)(?<![a-z])(?:banana|([a-z]+))(?![a-z])

2
另一种变化可能是匹配字符a-zA-Z,直到没有更多为止。然后断言香蕉不直接在左边。
[a-zA-Z]+(?![a-zA-Z])(?<!banana)

该模式匹配

  • [a-zA-Z]+ 匹配1个或多个字符 a-zA-Z
  • (?![a-zA-Z]) 负向先行断言,断言右侧直接没有 a-zA-Z
  • (?<!banana) 负向后行断言,断言左侧直接没有 banana

正则表达式演示


如果你想匹配 bananas 或者 straigtbanana,你可以断言左侧不是一个字符 a-zA-Z,且不以 banana 直接前缀。

[a-zA-Z]+(?![a-zA-Z])(?<!(?<![a-zA-Z])banana)

正则表达式演示


根据评论中@bobble bubble的建议,如果支持贪婪量词并使用不区分大小写匹配来缩短模式:

[a-z]++(?<!(?<![a-z])banana)
  • [a-z]++ 匹配范围在 a-z 之间的1个或多个字符(贪婪匹配,不回溯)
  • (?<! 负向先行断言,断言左侧没有
    • (?<![a-z])banana 负向先行断言,匹配前面没有 a-z 的 banana
  • ) 关闭负向先行断言

正则表达式演示


1
@JvdV 哦,我明白了,我认为第二个模式可以防止这种情况发生。 - The fourth bird
2
我喜欢这个,并受到你的第四个Bird模式的启发,想到了一个所有格量词,如果OPs正则表达式支持的话:/[a-z]++(?<!(?<![a-z])banana)/i - bobble bubble
@bobblebubble 好的,太棒了!如果你想要发布它,可以随时发布。 - The fourth bird
1
@bobblebubble,你发布了一些非常宝贵的内容,希望能够阅读到更多 :-) 如果我将它添加到回答中,可以吗? - The fourth bird
1
谢谢你,第四只鸟,非常感激,同样的也祝福你 :) 如果你愿意,我很高兴你能够包含它。 - bobble bubble
显示剩余3条评论

0
使用以下正则表达式以避免单个单词。
(?![banana])([a-zA-Z]+)

3
使用 [banana] 并不会像你认为的那样起作用。它是一个字符类,匹配其中列出的任一字符,相当于 [bna] - The fourth bird

0
/\b(((?!banana|apple|[^\p{L}]).)+)\b/gu

你需要使用单词边界表达式\b。这样可以排除匹配到的香蕉和苹果。

如果你想要排除大写字母的香蕉和苹果,可以在结尾处使用gui

\p{L}将匹配任何带有变音符号的单词。

如果你只需要排除香蕉,删除|apple即可。如果你需要添加更多的水果,比如橘子,在|apple后面加上|orange即可。


您可以在此处找到您的正则表达式 [链接](https://doregex.com/?urlconstruction=WyJ3aWxkIG5leHQgdHJ1ZSAwIiwiMTMiLCIiLCIiLCIiLCIiLCJiYW5hbmEiLCJhcHBsZSIsIiIsIiIsIiIsIiIsIiIsImZhbHNlIiwiZmFsc2UiLCIvYi9yL2UvYS9rLyIsImRpc2FibGVkIG5leHQgZmFsc2UgMCIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsImZhbHNlIiwiZmFsc2UiLCIvYi9yL2UvYS9rLyIsImRpc2FibGVkIG5leHQgZmFsc2UgMCIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsIiIsImZhbHNlIiwiZmFsc2UiLCIvYi9yL2UvYS9rLyIsInRydWUiLCJmYWxzZSIsImZhbHNlIiwidHJ1ZSIsImZhbHNlIiwidHJ1ZSIsImZhbHNlIl0=#crumbstart)。 - Radu Necsanu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接