【问题标题】:Java regex - comment detector inside stringJava regex - 字符串内的注释检测器
【发布时间】:2016-01-05 07:09:04
【问题描述】:

如何使用正则表达式对检测进行评论,但如果在字符串中,它应该不起作用。
例如:

//----------------------example-----------------------------------------
class fo{
    void foo(){
        /***print comment
        */
        System.out.println("example writing comment // this is comment");
        System.out.println("example comment 1 /* comment1 */");
        System.out.println("example comment 2 /* comment2 "+
                           "*/");
    }
}

这是我的评论检测模式:

Pattern.compile("^([^\"]|\"[^\"]*\")*?((/\\*([^\\*]|(\\*(?!/))+)*+\\*+/)|(//.*))");

但它不起作用

所以,// this is comment, /* comment1 */, /* comment2 "+ "*/" 不能匹配。

【问题讨论】:

标签: java regex string comments


【解决方案1】:

您可以通过注意注释前面必须有一个零个或多个“单位”的序列来解决这个问题,其中您将一个单位定义为:

  • " 以外的单个字符,或
  • 一个字符串文字,它是",后跟零个或多个非引号字符,后跟"

所以它应该可以制作图案

"^([^\"]|\"[^\"]*\")*?((/\\*([^\\*]|(\\*(?!/))+)*+\\*+/)|(//.*))"

我所做的是在你的模式之前

^([^"]|"[^"]*")*?

(当然,我必须转义 " 字符)。这意味着字符串以我在上面定义的 0 个或多个“单位”开头。最后一个*? 表示我们匹配尽可能少的单元数,以便我们找到跟随其中一个单元的第一个注释。

第一个^ 是将模式锚定到字符串开头所必需的,以确保匹配器不会尝试在字符串文字内开始匹配。我相信您可以使用\\G 而不是^,因为\\G 表示“输入的开始”。如果您尝试重复模式匹配并在字符串中查找所有 cmets,那会更好。

注意:我已经对此进行了测试,它似乎有效。

注意 2: 生成的正则表达式非常难看。 StackOverflow 上很流行认为正则表达式可以解决所有可能的问题,包括找到治愈癌症的方法;但是当结果像这样不可读时,是时候开始询问使用像循环这样无聊的东西是否会更简单、更可读、更可靠。我也不认为正则表达式更有效率,尽管我还没有检查过。

【讨论】:

  • 对不起,我已经更新了我的帖子,但它仍然无法正常工作。
  • 它按我预期的方式工作。如果它不适合您,请编辑您的问题并包括您正在使用的新代码、源字符串、您期望的输出以及实际的输出。 (或开始一个新问题。)包括每段相关的代码。特别是,如果您使用 group() 提取输入字符串的一部分,但它没有按预期工作,请告诉我们您是如何使用它的。
【解决方案2】:

您创建的正则表达式缺少一些转义字符,尽管这可能不适合您尝试执行的操作。这是您的更正版本。 Pattern.compile("((\\/\\*([^\\*]|(\\*(?!\\/))+)*\\+\\*\\+\\/)|(\\/\\/.*))");

但是,如果您希望在 IDE 中使用替换正则表达式,请使用 \".*?(\/\/.*?)\" 并将组 $1 替换为空字符串。

如果您想使用 Java 替换字符串,请尝试以下操作:

Pattern p = Pattern.compile("(.*?)(\\/\\/.*?)");
String output = "";
String input = "example writing comment // this is comment";
Matcher m = p.matcher(input);
if (m.find())
    output = m.replaceFirst("$1");

编辑

根据您的新问题,我提供了以下答案。但是,您的问题仍然不清楚。

Pattern p = Pattern.compile("^((.*?)((\\/\\/.*?)|(\\/\\*(.*)\\*\\/)(.*))?)$");
String output = "";
String input = "example writing comment // this is comment";
Matcher m = p.matcher(input);
if (m.find())
    output = m.replaceAll("$2$7");

此示例将替换字符串如下:

  • "example writing comment // this is comment"
    • 撰写评论示例
  • "example comment 1 /* comment1 */"
    • 示例评论 1
  • "example comment 2 /* comment2 "
    • 示例评论 2 /* 评论 2

【讨论】:

  • 您的正则表达式没有回答问题。 OP 希望能够进行忽略引用字符串内的 cmets 的匹配。而且我在您的正则表达式中看不到任何引号,因此您的正则表达式没有对带引号的字符串做任何特别的事情。
  • 此外,您的更正被误导了。正斜杠在正则表达式中没有特殊含义,因此转义它们是没有意义的。您转义的加号被用作它们前面的量词的所有格修饰符,因此转义它们会破坏正则表达式。
  • 首先,问题没有定义 OP 希望如何使用正则表达式的确切上下文。其次,我转义的“+”对于我将它们更改为的上下文是正确的; OP 误用了它们。第三,正斜杠在某些语言中确实有意义。例如,JavaScript 专门使用正斜杠来定义正则表达式。逃避它们是个好习惯。但是,我没有在我的 IDE 中测试任何东西,因为我远离装有 IntelliJ 或 Eclipse 的计算机。另外,我很少为 Java 编写正则表达式。
  • 我从未听说过在 Java 正则表达式中转义正斜杠是一种“好习惯”。
  • 我已经更新了我的帖子,我希望这个例子足够了
猜你喜欢
  • 1970-01-01
  • 2011-02-04
  • 1970-01-01
  • 2015-10-24
  • 1970-01-01
  • 2020-05-15
  • 1970-01-01
  • 2012-01-27
  • 1970-01-01
相关资源
最近更新 更多