正则表达式:不跟随指定字符的子字符串

3
假设一个正则表达式,用于测试任何包含子字符串 hello 的字符串,后面跟着任何不以 ! 或多个 ! 开头的字符串。

一些例子以便理解:

var regExp = /someExpression/;

regExp.test("hello"); // → true
regExp.test("hello!"); // → false
regExp.test("hello!!"); // → false
regExp.test("hello!sdkfjhsdfjkh"); // → false
regExp.test("hellos!dkfjhsdfjkh"); // → true
regExp.test("hello-!"); // → true
regExp.test("hello w34~342`!!"); // → true

我尝试了几种方法,以下是最佳方案:

var regExp = /.*hello[^!].*/;

这个正则表达式在我所能想到的所有情况下都能很好地工作,但有一种情况除外:"hello"

在这种情况下,[^!]期望一个字符。

如何改进这个正则表达式,使它也适用于这种情况?

非常感谢任何形式的帮助。


编辑 - 加分项:

同样适用于由!前导的hello,以使hello被接受,但!hello不被接受。

3个回答

3
你需要使用负向前瞻而不是否定字符类(仍然匹配并消耗字符):

您需要使用负向前瞻而不是否定字符类(仍然匹配并消耗字符):

var regExp = /.*hello(?!!).*/;

请看正则表达式演示
请查看regular-expressions.info以获取更多详细信息:
“负向先行断言”是不可或缺的,如果您想要匹配与其他内容不相邻的内容。在解释字符类时,本教程解释了为什么不能使用否定字符类来匹配一个不带“u”的“q”。负向先行断言提供了解决方案:q(?!u)。负向先行断言构造是一对括号,其中开括号后跟一个问号和一个感叹号。
编辑:
由于JS正则表达式引擎不支持后行断言,因此需要匹配(^|[^!])hello(其中(^|[^!])匹配字符串的开头或除“!”之外的任何符号),然后使用JS字符串方法进行必要的操作。

.* 有用吗?为什么?请注意,使用的方法是 test - Casimir et Hippolyte
谢谢你的回答。非常完美。我知道这通常不被接受,但你能否推荐另一个案例的解决方案呢?我正在尝试为以 ! 为前缀的 hello 找出相同的原则。是否有类似于回溯的东西?(这也在编辑中添加到问题中) - Selfish
对于JS来说,情况会有所不同,因为JS不支持向后查找。您需要匹配 (^|[^!])hello,然后使用JS字符串和其他方法来操作匹配。 - Wiktor Stribiżew
谢谢!那真是太有帮助了。 - Selfish

1

仅针对这些情况,否定/hello!/是完全有效的:

var regExp = /hello!/;

!regExp.test("hello"); // → true
!regExp.test("hello!"); // → false
!regExp.test("hello!!"); // → false
!regExp.test("hello-!"); // → true
!regExp.test("hello w34~342`!!"); // → true

请看:

查看:https://regex101.com/r/xI1mG0/1


好的方法!<°)))))))))))> - Casimir et Hippolyte
虽然正确,但这严格来说不是被要求的。谢谢你的回答。 :) - Selfish

0

使用简单的字符串结尾交替:

/hello([^!]|$)/.test(str);

感谢您的回复。/"hello([^!]|$)"/.test("hello"); 测试结果为 false,这不太好。 - Selfish
@NitaiJ.Perez:抱歉,我犯了一个错误(已经纠正)。 - Casimir et Hippolyte
抱歉,已经解释过否定字符在这里不起作用。这也是我尝试的方式。/hello([^!]|$)/.test("hello!a");测试为false,但实际上不应该是这样。 - Selfish
@NitaiJ.Perez:如果我理解得正确,你的问题是"hello!a""hello!"应该返回false,对吗?(因为后面跟着一个! - Casimir et Hippolyte
没错,那是个打字错误。 :) 我的意思是针对 helloa! 进行测试,测试结果是好的。谢谢! - Selfish

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