【问题标题】:Regex which ignores comments忽略评论的正则表达式
【发布时间】:2013-10-07 18:17:24
【问题描述】:

作为一个正则表达式初学者,我需要一些帮助来编写一个正则表达式。它应该匹配一个特定的模式,比如说“ABC”。但是在注释中使用该模式时不应匹配该模式(' 是注释符号)。所以XYZ ' ABC 不应该匹配。 x("teststring ABC") 也不应该匹配。但是ABC("teststring ' xxx") 必须匹配到结束,即xxx 没有被切断。 还有人知道一个免费的正则表达式应用程序,你可以用它来“调试”你的正则表达式吗?我经常无法识别我的尝试有什么问题。谢谢!

【问题讨论】:

    标签: regex


    【解决方案1】:

    有些人会以RegexBuddy 发誓。我从未使用过调试器,但我建议您不要使用它提供的正则表达式生成器。这只是个坏主意。

    您可以使用您使用的任何正则表达式风格来完成此任务,但总的来说,我认为您会发现以“硬”方式执行此操作更容易且更易于维护。正则表达式适用于正则语言,嵌套任何内容通常意味着正则表达式不是一个好主意。正则表达式语法的现代扩展意味着它可能是可行的,但它不会很漂亮,而且你肯定不会记得早上发生了什么。一个正则表达式失败的地方(即使是现代的非常规扩展)是解析嵌套结构 - 试图解析任何混合的 cmets、引用的字符串和括号很快就会变成一个难以理解和无法维护的混乱。不要误会我的意思——我喜欢在正确的地方使用正则表达式。这不是其中之一。

    【讨论】:

    • 是的,我注意到了。但我必须坚持使用正则表达式来解决设计问题。所以我决定在应用正则表达式之前手动去除关键部分。
    【解决方案2】:

    关于好的正则表达式工具这个话题,我很喜欢RegexBuddy,但它不是免费的。

    除此之外,如果您还需要检查内部字符串分隔符等各种情况,则正则表达式是错误的工具。你需要一个finite-state machine

    【讨论】:

    • -1 因为我讨厌 RegexBuddy,但 +2 表示“错误的工具”。这一次你赢了,RegexBuddy! \
    • +1 for RegexBuddy(并且正则表达式是错误的工具) - 它非常适合测试或分解正则表达式。我不需要它的“神奇”功能,只需要基本功能。
    • 是的,我经常使用 RegexBuddy 来测试正则表达式。当您不必费心记住所有各种正则表达式运算符时,这也很好:p
    【解决方案3】:

    奇怪的是,很多人推荐他们最喜欢的工具,但没有人为手头的问题提供解决方案。 (我是 RegexBuddy 的开发者,所以我不会推荐任何工具。)

    没有匹配 Y 的好方法,除非它是带有单个正则表达式的 XYZ 的一部分。您可以做的是编写一个匹配 Y 和 XYZ 的正则表达式:Y|XYZ。然后使用一些额外的代码来处理 Y 的匹配,并忽略 XYZ 的匹配。一种方法是使用捕获组:(Y)|XYZ。现在您可以处理第一个捕获组的匹配项。当 XYZ 匹配时,捕获组不匹配任何内容。

    要为您的 VB 风格的 cmets 执行此操作,您可以使用正则表达式:

    '.*|(ABC)
    

    这个正则表达式匹配单引号和直到行尾的所有内容,或 ABC。此正则表达式将匹配所有 cmets(无论是否包括 ABC)。捕获组将匹配所有出现的 ABC,但 cmets 中的除外。

    如果您希望您的正则表达式同时跳过 cmets 和字符串,您可以将字符串添加到您的正则表达式中:

    '.*|"[^"\r\n]*"|(ABC)
    

    【讨论】:

    • 问题是,撇号出现在一组双引号中的情况呢?然后他希望它匹配。很抱歉,但 regex 确实是适合这里工作的错误工具,即使您确实设法编写了一个来完成它。
    • 此外,我们正在提供有关工具的建议,因为 OP 需要它们。诚然,他要求提供免费工具,但我觉得 RegexBuddy 无论如何都值得插入(就软件而言,它并不昂贵)。
    • 正则表达式是否是适合该工作的工具取决于该工作是什么。例如。如果他在一堆文本文件中进行一次性编辑,那么文本编辑器中的快速正则表达式就可以完成这项工作。
    【解决方案4】:

    我发现正则表达式的最佳“调试器”只是在交互式环境中尝试大量的小细节。对于 Python,ipython 很棒;对于 Ruby,irb,对于命令行类型的东西,sed...

    一次尝试一些小片段,确保你理解它们,然后再添加一点点。冲洗并重复。

    【讨论】:

    • 注意这里的正则表达式风格之间的细微差别——在 Python 中有效的东西不一定在 JavaScript 中有效。
    • 绝对。因此对不同语言有不同的建议。需要牢记的重要一点,也是专门调试的另一个原因。
    【解决方案5】:

    对于NET开发你不妨试试RegexDesigner,这个工具可以为你生成代码(VB/C#)。对于我们 Regex 初学者来说,这是一个非常好的工具。

    link text

    【讨论】:

      【解决方案6】:

      这是我对这个问题的解决方案: 1. 在哈希中找到一个存储所有 cmets 2.做你的正则表达式替换 3.将cmets带回归档

      节省您的时间:-)

      string fileTextWithComments = "Some tetx file contents";
      
      Dictionary<string, string> comments = new Dictionary<string, string>();
      
      // 1. Find a store all your comments in hash
      Regex rc = new Regex("(?:/\\*(?:[^*]|(?:\\*+[^*/]))*\\*+/)|(?://.*)");
      MatchCollection matches = rc.Matches(fileTextWithComments);
      
      int index = 0;
      foreach (Match match in matches)
      {
          string key = string.Format("/*Comment#{0}*/", index++);
          comments.Add(key, match.Value);
          fileTextWithComments = fileTextWithComments.Replace(match.Value, key);
      }
      
      // 2. Do your regexp replacement
      Regex r = new Regex("YOUR REGEXP PATTERN");
      fileTextWithComments = r.Replace(fileTextWithComments, "NEW STRING");
      
      
      // 3. Bring comments back to file :-)
      foreach (string key in comments.Keys)
      {
          string comment = comments[key];
          fileTextWithComments = fileTextWithComments.Replace(key, comment);
      }
      

      【讨论】:

        【解决方案7】:

        你能澄清一下吗?我读了三次,我认为当给定模式显示为文字时,你想匹配它。就像不作为评论或字符串的一部分一样。

        作为单个正则表达式,您的要求非常棘手。因为你想跳过字符串。一行中有多个字符串会使事情复杂化。

        我什至不会尝试在一个正则表达式中做到这一点。相反,我首先将每一行通过一个过滤器,以删除字符串,然后按该顺序进行 cmets。然后尝试匹配您的模式。

        在 Perl 中,因为它的正则表达式处理能力。假设@lines 是您要匹配的行列表,而 $pattern 是您要匹配的模式。

        @matches =[];
        for (@lines){
          $line = $_;
          $line ~= s/"[^"]*?(?<!\)"//g;
          $line ~= s/'.*//g;
          push @matches, $_ if $line ~= m/$pattern/;
        }
        

        第一个替换查找以双引号开头并以第一个非转义双引号结尾的任何模式。使用退格的标准转义字符。 接下来剥离 cmets。如果模式仍然匹配,则将该行添加到匹配列表中。

        它并不完美,因为它无法区分"a\\""a\" 之间的区别。第一个通常是有效的字符串,后者不是。无论哪种方式,这些替换都将继续寻找另一个“,如果找不到,则字符串不会被丢弃。我们可以使用另一个替换来用其他东西替换所有双反斜杠。但是如果你的模式会导致问题” relooking 包含反斜杠。

        【讨论】:

          【解决方案8】:

          如果您只有单行 cmets,您可以使用 zero width look-behind assertion,但如果您使用多行 cmets,则有点棘手。

          最终,您确实需要使用某种解析器来解决此类问题,因为注释的定义实际上是由语法驱动的。

          This answer 到一个不同但相关的问题看起来也不错...

          【讨论】:

            【解决方案9】:

            如果您有 Emacs,则有一个名为“regexp-builder”的内置正则表达式工具。我不太了解您的正则表达式问题的具体细节,无法提出答案。

            【讨论】:

              【解决方案10】:

              RegEx1:(-user ")(.*?)"

              主题:report -user "test user" -date 1/4/13 -day monday -daterange "1/4/13 1/20/13" -

              结果:-user "test user"

              正则表达式2:(-daterange ")(.*?)"

              主题:report -user "test user" -date 1/4/13 -day monday -daterange "1/4/13 1/20/13" -

              结果:-daterange "1/4/13 1/20/13"

              RegEx3:(-date )(.*?)( -)

              主题:report -user "test user" -date 1/4/13 -day monday -daterange "1/4/13 1/20/13" -

              结果:-date 1/4/13 -

              RegEx4:(-day )(.*?)( -)

              主题:report -user "test user" -date 1/4/13 -day monday -daterange "1/4/13 1/20/13" -

              结果:-day monday -

              如果没有找到先搜索带引号的值,搜索不带引号的参数。这期望参数只出现一次。它还期望命令要么;使用引号来封装一个没有引号的字符串,或者;在第一个位置使用除引号以外的任何字符,在下一个参数之前不出现“-”,并且有一个尾随“-”(将其添加到正则表达式之前的字符串中)。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2017-08-04
                • 1970-01-01
                • 2015-04-09
                • 1970-01-01
                • 2012-08-18
                相关资源
                最近更新 更多