仅匹配未转义字符的正则表达式

11

好的,我正在尝试使用正则表达式来匹配某个字符的实例,但仅当它没有被转义(用反斜杠)时。我决定使用负向回顾类似于这样:

(?<!\\)[*]

使用字符串foo*foo\*时,此方法能够按预期成功和失败。

但是,对于字符串foo\\*等不起作用,即特殊字符前面有反斜杠转义另一个反斜杠的情况(这是一种被转义的转义序列)。

是否可以使用负回顾后发断言(或其他技术),仅在特殊字符前面有奇数个反斜杠的情况下跳过它们?


2
你使用的编程语言是哪种? - Avinash Raj
重复问题。另外,您没有告诉我们您使用的编程语言,并且您肯定没有搜索至少20秒钟以找到解决方案。 - user4454229
@AvinashRaj 在我的情况下,Swift(更具体地说,我正在使用NSRegularExpression)似乎没有缺少任何正则表达式功能,所以我认为不需要提及它。@rac 你肯定没有花超过20秒钟查看你发布的重复内容,因为它并没有涵盖我的确切情况; 即-它的转义序列不能用于转义自身。 - Haravikk
1
@rac 这不是重复的问题,因为其他帖子没有提出这个问题,也没有解决这个问题的答案。 - Tomáš Zato
2个回答

13

我找到了以下解决方案,它适用于NSRegularExpression,但也适用于我尝试过的支持负向回顾后发断言的每个正则表达式实现:

(?<!\\)(?:(\\\\)*)[*]
在这种情况下,第二个未匹配的右括号与任何一对反斜杠进行匹配,有效地消除它们,此时负回顾可以按预期比较任何剩余的(奇数编号的)反斜杠。

2
这个可以工作,但它不能匹配未转义的反斜杠 - 你知道如何扩展它以允许这样吗? - Cocowalla
在这里,"(.?(?<!\)(?:(?:\\)))"匹配由" "分隔的字符串中未转义的反斜杠。 - Denis Giffeler
@DenisGiffeler 反斜杠转义和代码块也适用于注释,我想你是想发布 "(.*?(?<!\\)(?:(?:\\\\\\)*))" - undefined

2
一个回溯无法解决这个问题。唯一的方法是首先匹配转义字符以避免它们,并找到未转义的字符:
您可以使用捕获组从结果中隔离未转义的字符:
(?:\\.)+|(\*)

或者使用 \K(pcre/perl/ruby)功能,它会从结果中删除左侧的所有内容:
(?:\\.)*\K\*

或者使用回溯控制字符(pcre/perl)来跳过转义字符:

(?:\\.)+(*SKIP)(*FAIL)|\*

唯一可以使用回顾后发表达式的情况是使用 .net 框架,它允许无限长度的回顾后发表达式:

(?<!(?:[^\\]|\A)(?:\\\\)*\\)\*

或者更有限地使用Java:

(?<!(?:[^\\]|\A)(?:\\\\){0,1000}\\)\*

1
嗯,实际上我刚刚尝试了(?<!\\)(?:\\\\*)[*],这似乎可以按预期工作,通过有效地消除成对的反斜杠,只留下单个反斜杠来前置搜索模式(或者什么也不留或者字面量)。如果没有任何不合法的原因,我可能会将其添加为我的答案。 - Haravikk

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