负匹配的正则表达式

时间:2018-08-01 03:31:40

标签: regex tcl

我想做一个正则表达式以获取评论。

我要区分单个评论/*afdafad */和多个评论/* appple .......

可以单条评论,但我对多行评论感到困惑。

我尝试过:

set line "/* using cmos4 delaymodel */"
regexp {\/\*.+[^*][^/]} $line
puts [regexp -inline {\/\*.*[^\*][^/]} $line]

输出:

{/* using cmos4 delaymodel *}

我无法逃脱*符号。

我希望,我应该匹配/*中包含*/但没有$line的行,但是我失败了,那么如何修改正则表达式?

3 个答案:

答案 0 :(得分:1)

严格来说,这不是以正则表达式为中心的问题的答案。我只是想指出,在Tcl中,您不必针对特定情况使用正则表达式(尤其是如果您假设您的评论来源格式正确等)。

建议

您可能要考虑进行文本修饰,即将注释的源预处理为包含Tcl命令序列[cmd ...]的源。在您的情况下,分隔符的开始和结束注释变成命令序列的开始和结束括号。执行的命令可以是下面的过程,例如comment,用于捕获并进一步处理您的注释正文,或者将占位符返回到处理后的文本中。然后,通过在预格式化的源上应用[subst]来触发实际的命令执行(即注释捕获)。

观看:

set input {/* this is a
    multiline comment */ /* This is a [single line] comment */}

proc comment {body} {
    puts "got a comment: '$body'"
    return "/* ---%<--- */"
}

set tmp [string map {"[" "\[" "]" "\]" "/*" "[comment {" "*/" "}]"} $input]

set output [subst -novariables -nobackslashes $tmp]

评论

  • 很明显,这没有给您直接方法来验证注释语法的使用等。您可以假定使用有效的语法,或者可以检查预格式化的Tcl字符串是否为完整的Tcl脚本:[info complete $tmp]。不过,这只会捕获某些出现的不平衡括号(注释定界符)。

  • 单行注释与多行注释之间的区别对于捕获注释并不重要。

  • 根据源语法,您必须保护在[subst]期间可能被误解为Tcl语法的字符。例如,括号是真正的语法元素或$。对于使用[string map]使用转义符和对[subst]-novariables-nobackslashes)的限制,必须对此进行控制。

答案 1 :(得分:0)

它不起作用,因为尽管[^\*]不接受*,但[^/]可以接受。引擎通过让[^\*]消耗*之前的空白来解决匹配问题。

如果愿意

regexp -inline {(/\*.*)\*/} $line

你得到

{/* using cmos4 delaymodel */} {/* using cmos4 delaymodel }

这可能是最简单的。您可以通过以下任一方式获取捕获信息:

lindex [regexp -inline {(/\*.*)\*/} $line] 1
regexp {(/\*.*)\*/} $line -> a

在后一种情况下,变量->获得完全匹配,而a获得捕获。

如果注释中不包含任何星号,则还可以使用正则表达式/\*[^*]*,即匹配从注释开始到第一个星号(但不包括第一个星号)的所有内容。

(而且您不需要在Tcl正则表达式中转义斜杠,它们是斜杠友好的。)

答案 2 :(得分:0)

假设您要匹配的正则表达式不包含诸如注释之类的字符串之类的不规则字符(例如在JavaScript中,诸如var s = '/* incorrect comment */'之类的字符串),并且您对Tcl的正则表达式不太熟悉,则您区分单个注释的方法也很有可能是错误的。这是因为默认情况下,Tcl的正则表达式中的.与换行符匹配。

因此,仅用于单行注释,您可能需要以下内容:

regexp -linestop -inline -- {/\*.*\*/} $line

在没有-linestop的情况下,以上内容将能够匹配单行注释和多行注释。

并且仅对于多行注释,类似于以下内容可在注释内强制换行符:

regexp -linestop -inline -- {/\*(?:[^*]|\*[^/])*?(?:[\r\n]+.*?)+\*/} $comment

注意:.*贪婪的第二个+的惰性对正则表达式没有影响,因为所有这些都是惰性的,这是由于第一个量词是惰性的。我使第二个.*变得很懒,因为在我看来,这绝对是个懒惰。它处理的边缘情况如下:

/* this is a
   multiline comment */ /* This is a single line comment */