JavaScript正则表达式匹配以某些字符结尾但不以特定组合结尾的字符串

17
假设我想使用JavaScript匹配一个以 [abcde]* 结尾但不以 abc 结尾的字符串。

所以正则表达式应该匹配 xxxaxxxbcxxxabd,但不匹配 xxxabc
我感到非常困惑。
编辑:由于某些原因,我必须使用正则表达式,不能使用 if (str.endsWith("abc")) 的方式。

[abcde]* 真的应该是 [abcde]+ 吗?否则 xxx 就可以匹配成功了。 - polygenelubricants
5个回答

31
解决方案很简单:使用负向先行断言:
(?!.*abc$)

这个断言表明该字符串不以abc结尾。

您提到您还需要该字符串以[abcde]*结尾,但是*表示它是可选的,因此xxx也可以匹配。我猜想您真正想要的是[abcde]+,它只是表示需要以[abcde]结尾。在这种情况下,断言应该如下:

(?=.*[abcde]$)(?!.*abc$)

参见regular-expressions.info获取正向和负向预查的教程。


我有些不太熟悉Javascript语言,所以不想提供实际的Javascript正则表达式(不过我相信如果支持这些断言,它们会起作用——根据regular-expressions.info,Javascript支持正向和负向预查)。在Pointy和Alan Moore的评论的帮助下,我认为正确的Javascript正则表达式是:

var regex = /^(?!.*abc$).*[abcde]$/;
请注意,此版本(感谢Alan Moore)不再需要正向先行断言。它简单地匹配.*[abcde]$,但首先要确保^(?!.*abc$)

那不起作用。尝试在Javascript中使用 - 第二个正则表达式匹配“xxabc”。 - Pointy
@Pointy: 在JavaScript中,"xxabc".match(/^(?=.*[abcde]$)(?!.abc$).$/)是null(尽管我不确定这是否是正则表达式的正确方法)。 - polygenelubricants
尝试使用regex.test("xxabc") - 返回布尔值 - Pointy
1
我不认为正向预查是必要的:^(?!.*abc$).*[abcde]$ - Alan Moore
@Alan:没错,你说得对 =)建议已经采纳并给予完整的认可。 - polygenelubricants
显示剩余2条评论

16

这个问题要么没有明确定义,要么每个人都忽略了一个简单的答案。

var re = /abc$/;

!re.test("xxxa");    // pass
!re.test("xxxbc");   // pass
!re.test("xxxabd");  // pass
!re.test("xxxabc");  // fail

所有这些都以/[abcde]*/结尾。


简单而聪明。只需为最后一个字符和“and”布尔结果进行测试即可。 - Kangur
同意,非常简单,但对于我的用例,在开头加上!是行不通的。 - Endless

2
首先,注意每个字符串都以[abcde]*结尾,因为它允许零宽度。因此,我们只需要寻找一个正则表达式来匹配不以abc结尾的字符串。很容易。
([^c]|[^b]c|[^a]bc)$

这是一些与 c 不同的东西,不是跟随 b 后面的 c ,也不是跟随 a 后面的 bc ,无论哪种选项,都要跟随字符串的结尾。


1
我想对@maček说,你的回答简单明了,以!开头。但是,我真的希望非运算符在正则表达式内部,这样我就可以在Array::someArray::filterArray::findArray::findIndex中使用它,而无需创建函数或while循环。
以下是一个示例:

var items = ["ja", "ka", "mf", "bg", "vb", "b"]
var regex = /^((?!a$|b$).)*$/; // match a string that doesn't end with a or b

var matched = items.filter(RegExp.prototype.test, regex);

alert(matched); // result: ["mf", "bg"]


0

嗯...

var regex = /(ab[abde]|[abcde])$/; // wrong

可能吗?等等,不对;稍等:

var regex = /(ab[abde]|([^a].|.[^b])[abcde]|\b.?[abcde])$/;

所以这是由“ab”后跟“a”、“b”、“d”或“e”组成的;或者任何第一个字符不是“a”或第二个字符不是“b”的两个字符序列,后跟“a”到“e”;或者任何单词边界后面跟着任何字符(可能)后面跟着“a”到“e”。最后一条子句是为了处理短字符串;这有点像作弊,但在这种情况下它起作用。


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