如果匹配,正则表达式会消耗一个字符,但不会消耗

时间:2018-03-02 11:58:56

标签: javascript regex regex-lookarounds

我正在尝试编写一个正则表达式,它将捕获'@'字符的所有实例,除了,当两个这样的字符连续出现时(实质上是转义序列)。例如:

abd@ajk@应匹配

abd@@ajk:没有匹配

abd@@@ajk final @应匹配。

abd@@@@ajk:没有匹配

这几乎与负前瞻表达式@(?!@)一起使用,但由于第二个@未被消耗,因此两个@符号中的最后一个仍将匹配。我认为我想做的是向前看@,但如果它在那里就消耗它;否则,不要消耗它。这可能吗?

编辑:我正在使用Javascript,遗憾的是它排除了几种不错的方法:(

2 个答案:

答案 0 :(得分:2)

在JavaScript中,要在未转义的@处拆分字符串,您实际上可以匹配文本块@@(转义@)和除@以外的任何字符:

var strs = ['abd@ajk','abd@@ajk','abd@@@ajk','abd@@@@ajk'];
var rx = /(?:[^@]|@@)+/g;
for (var s of strs) {
	console.log(s, "=>", s.match(rx))
}

正则表达式是

/(?:[^@]|@@)+/g

请参阅its demo

<强>详情

  • (?: - 启动与两个备选方案中的任何一个匹配的非捕获组:
    • [^ @] - any char other than @`
    • | - 或
    • @@ - 2 @ s
  • )+ - 重复匹配1次或更多次。

g修饰符在输入字符串中查找所有匹配的匹配项。

答案 1 :(得分:2)

由于你没有为你的问题标记编程语言,这里是我的2美分Java:

(?<=(?<!@)(?:@@){0,999})@(?!@)

Java不支持无限的lookbehinds,但是在这里我有明确指定@ 999偶数出现的最大值。

JavsScript

许多浏览器尚未实现和支持JavaScript中的Lookbehinds。如果您尝试在JS中执行此操作,那么这将是您的工作解决方案:

方法1

((?:[^@]*(?:@@)+[^@]*)+)|@
  • (?:[^@]*(?:@@)+[^@]*)+匹配@@次出现及其所有前导/尾随字符
  • |@或单个@

JS代码:

str.split(/((?:[^@]*(?:@@)+[^@]*)+)|@/).filter(Boolean);

方法2(推荐)

或者如果您在使用match()时没有问题,这会更清洁,当然更快:

(?:[^@]*(?:@@)+[^@]*)+|[^@]+

JS代码:

console.log(
  "aaaa@@@@@@@bbb@aa@@@cccc@@ddddd@".match(/(?:[^@]*(?:@@)+[^@]*)+|[^@]+/g)
);