注释的正则表达式,但不在“字符串”内/不在另一个容器中

Posted

技术标签:

【中文标题】注释的正则表达式,但不在“字符串”内/不在另一个容器中【英文标题】:Regular Expression for comments but not within a "string" / not in another container 【发布时间】:2012-03-01 12:07:35 【问题描述】:

所以我需要一个正则表达式来查找单行和多行 cmets,但不是在字符串中。 (例如"my /* string"

用于测试(# 单行,/* & */ 多行):

# complete line should be found
lorem ipsum # from this to line end
/*
  all three lines should be found
*/ but not here anymore
var x = "this # should not be found"
var y = "this /* shouldn't */ match either"
var z = "but" & /* this must match */ "_"

所以语法显示真的很好;我基本上想要所有的灰色文本。 我不在乎它是一个正则表达式还是两个分隔符。 ;)

编辑:还有一件事。相反的也会让我满意,搜索一个不在评论中的字符串 这是我当前的字符串匹配:"[\s\S]*?(?<!\\)"(实际上:不适用于"\\"

EDIT2: 好的,最后我编写了自己的评论解析器 -.- 如果其他人对源代码感兴趣,请从这里获取:https://github.com/relikd/CommentParser

【问题讨论】:

你用它做什么?如果您有一个特定的目的,那么有人可能已经为您写了一些东西。 为此所需的正则表达式是......非常重要的。您打算使用哪个程序(明语)?我有一个可以处理 C /* ... */ cmets 的 C 'comment stripper';它不是为处理 # cmets 而设计的(尽管它确实可以处理 C++ // cmets OK)。它有一个逆模式 - 打印 cmets 而不是非评论材料。但这是一个不可忽略的 C 代码量。 我正在用 ObjC 写一个小的语法高亮,但我认为会有一个通用的正则表达式,而不是按字符搜索字符:/ 排除字符串是正则表达式不容易处理的复杂性的主要来源之一。 C cmets 的完整语义是可怕的。开始注释的斜杠和星号可以由任意数量的反斜杠换行字符对分隔,例如;评论末尾的星号斜线同上。从技术上讲,C++ // 注释可以在两个斜杠之间有任意数量的反斜杠换行符对。因此,任何正则表达式都必须使用一种语言,在这种语言中,您不会为 C 风格的 cmets 读取“一次一行”(#...EOL cmets 更容易)。 另外,请考虑以下问题。您可能希望 #/* 成为单行注释。而且您可能不希望 #*/ 关闭现有评论。 【参考方案1】:

这是一种可能性(它确实有一个致命弱点):

(#[^"\n\r]*(?:"[^"\n\r]*"[^"\n\r]*)*[\r\n]|/\*([^*]|\*(?!/))*?\*/)(?=[^"]*(?:"[^"]*"[^"]*)*$)

在行动here

带有 GLOBAL 和 DOTALL 标志,但不是 MULTILINE 标志。

正则表达式的解释:

(
  #[^"\n\r]*                         Hash mark followed by non-" and non-end-of-line
    (?:"[^"\n\r]*"[^"\n\r]*)*        If any quotes in the comment, they must be balanced
    [\r\n]                           Followed by end-of-line ($ except we 
                                      don't have multiline flag)

  |                                  OR
  /\*([^*]|\*(?!/))*?\*/             /* xxx */ sort of comment
  )                                  BOTH FOLLOWED BY
(?=[^"]*(?:"[^"]*"[^"]*)*$)           only a *balanced* number of quotes for the 
                                      *rest of the code :O!*

但是,这依赖在整个文本中使用平衡引号(它也不考虑转义引号,但很容易修改正则表达式以将其考虑在内)。

如果用户的评论中带有“不平衡...砰。你完蛋了!

html/代码解析之类的东西通常不推荐使用正则表达式,但如果您可以依靠在定义字符串等时引号必须平衡这一事实,您有时可以侥幸逃脱。

由于您也在解析 cmets,它具有 无集合结构(即您不能保证 cmets 中的引号是平衡的),您将无法找到适用于此处的正则表达式解决方案。

您想到的任何事情都可能被某处评论中的不平衡引号(比如评论是# remove all the " marks)或多行字符串(在给定的行上可能存在不平衡引号)所欺骗。

底线 - 您可能可以制作一个适用于大多数情况的正则表达式,但并非适用于所有情况。要获得无懈可击的东西,您必须编写一些代码。

【讨论】:

+1 因为它比我尝试了几个小时的所有方法都好:D。你可以试试别的方法吗?也许找到不在评论中的字符串更容易。 (至少一个单行字符串)【参考方案2】:

我会为此使用两个正则表达式:

    /(\/\*.*?\/)|(#.+?$)/m查找所有cmets,“m”修饰符是启用多行 /"[^"]*?"/ 查找所有字符串

如果您首先对 cme​​ts 应用突出显示,并且仅在对字符串应用突出显示,则无效的 cmets 应该会消失。

【讨论】:

这正是我想要避免的 ^^。我目前有一个要加载的正则表达式列表以及相互覆盖的字符串和 cmets。因此,如果我先为 cmets 应用一种颜色,然后为字符串应用另一种颜色,它们也会在 cmets 中着色 你是对的,没有想到这一点:) 不知道你是否可以不用解析器。 您是否考虑过检查每个匹配项是否包含其他匹配项并在这种情况下覆盖它们? 我觉得太过分了。假设我有一个大文档,并且在用户键入每个单个字符后,代码都会被着色。我想如果我没有得到答案,我只会在 cmets 内显示彩色字符串。 (不是最好的解决方案,但比两者的混合更快)

以上是关于注释的正则表达式,但不在“字符串”内/不在另一个容器中的主要内容,如果未能解决你的问题,请参考以下文章

不在正则表达式中

C# 正则表达式子字符串应该在开始和结束但不在中间

SQLite正则表达式用于查找字符串不在预定义集中的行

正则表达式用逗号分隔 - 不在括号或单引号内

如何在.net正则表达式中找到不在括号内的逗号?

非捕获组不在正则表达式中工作