只有当子模式不匹配时,正则表达式才会进行匹配。

4
我将尝试从文件中匹配C风格的注释,但仅在注释不以由@引入的特定标签开头时才匹配。
例如,从以下代码中:
/* some comment to match */
/* another comment.
this should match also */
/*@special shouldn't match*/

是否仅使用正则表达式可以实现这一点?

我正在尝试使用JavaScript实现的正则表达式。

3个回答

4
/\*\s*(?!@)(?:(?!\*/).)*\*/

这段代码的作用是:

/\*               // 匹配 "/*"
\s*               // 可选空格
(?!@)             // 不跟随 "@"
(?:               // 不捕获...
   (?!\*/).       // ...任何不是 "*/" 的字符
)*                // 但尽可能多地匹配
\*/               // 匹配 "*/"

在“全局”和“dotall”模式下使用(例如点号应该匹配换行符)

通常的警告:与所有使用正则表达式执行的解析任务一样,如果存在嵌套模式和破碎的输入,则此操作将失败。

emk指出了一个很好的例子,即使输入有效也会导致此表达式失效。这是无法避免的,因为正则表达式不适用于解析。如果您确定这样的事情绝不会发生在您的输入中,则正则表达式仍可能对您有用。


只是为了严谨起见,\s*(?!@).?并不意味着你认为的那样,而是一个零宽度的负向先行断言。这意味着一旦你匹配了尽可能多的空格(\s*),只有当下一个字符不是@时才继续匹配。.?是不必要的。 - Anthony Roy
只是为了追求严谨,如果我不知道负向先行断言,我怎么可能写出来呢?;-) 不过你说".?"是不必要的,这一点是正确的。我已经将其删除了。 - Tomalak

1
你可以从这样的东西开始:
/\*[^@]

但是一般来说,您不希望使用正则表达式匹配C风格的注释,因为存在讨厌的边角情况。请考虑:

"foo\" /* " " */ "

这段代码中没有注释(它是两个字符串字面量的编译时连接),但如果没有真正的解析器,你将很难对其进行解析。(从技术上讲,你可以使用正则表达式,因为你只需要一个简单的有限状态机。但这是一个非常恶心的正则表达式。)


指出风险部分加1。我认为你不能使用正则表达式成功解析类似C的语言。即使是非常丑陋的正则表达式也不行。 - Tomalak
尽管你不能用正则表达式解析任意的C代码,但你实际上可以去除注释。我以前曾经编写过一个状态机来完成这个任务,而且任何此类状态机都可以被转换为正则表达式。但我认为如果没有大量努力思考,我无法手动构建它。 - emk

0

使用负向先行断言


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