【问题标题】:Java Regex to filter lines with comment not working as expectedJava Regex 过滤带有注释的行未按预期工作
【发布时间】:2017-01-08 11:43:27
【问题描述】:

我整理了这个简化版本的代码来演示这个问题:

public static void main(String []args){
    String content="1 [thing i want]\n" +
    "2 [thing i dont want]\n" +
    "3 [thing i dont want] [thing i want]\n" +
    "4 // [thing i want]\n" +
    "5 [thing i want]  // [thing i want]\n";

    String BASE_REGEX = "(?!//)\\[%s\\]";
    Pattern myRegex = Pattern.compile(String.format(BASE_REGEX, "thing i want"));
    Matcher m= myRegex.matcher(content);
    System.out.println("match? "+m);
    String newContent = m.replaceAll("best thing ever");
    System.out.println("regex "+myRegex);
    System.out.println("content:\n"+content);
    System.out.println("new content:\n"+newContent);
 }

我希望我的输出是:

new content:
1 best thing ever
2 [thing i dont want]
3 [thing i dont want] best thing ever
4 // [thing i want]
5 best thing ever  // [thing i want]

但我明白了:

new content:
1 best thing ever
2 [thing i dont want]
3 [thing i dont want] best thing ever
4 // best thing ever
5 best thing ever  // best thing ever

如何修复正则表达式?

未修改的字符串:

content:
1 [thing i want]
2 [thing i dont want]
3 [thing i dont want] [thing i want]
4 // [thing i want]
5 [thing i want]  // [thing i want]

【问题讨论】:

  • (?!//) 始终为真,因为下一个使用的字符是 [。您似乎避免在单行 cmets 中替换,对吗?匹配那些 cmets,并且只替换其他上下文中的匹配项。
  • 我看不出你想要的东西和不想要的东西之间的关系。您能否发布一个单独的字符串 content 的文本块,如果打印出来的话?
  • @sln 。我将其添加到原始问题中。

标签: java regex parsing comments regex-lookarounds


【解决方案1】:

没有真正简单的方法来测试内联注释中是否包含某些内容。 Java 正则表达式引擎能够向后看,但“距离”有限(换句话说,它允许有限的可变长度向后看),我不确定使用此功能构建模式是否非常有效。

您可以做的是从每行的开头检查所有内容:

(?m)((?:\G|^)[^\[/\n]*+(?:\[(?!thing i want\])[^\[/\n]*|/(?!/)[^\[/\n]*)*+)\[thing i want\]

(转义每个反斜杠以在 Java 中写入模式字符串)

替换:

$1best thing ever

说明:目标是捕获从目标之前的行开头或从同一行中的上一个目标到下一个目标的所有内容。通过这种方式,您可以在目标出现之前准确描述允许或不允许的内容(所有不是目标或两个连续斜线)

(?m) # switch the multi-line mode on: the ^ means "start of the line"
(    # open the capture group $1
    (?:    # non-capturing group: two possible starts
        \G # contiguous to a previous match (on the same line) 
      |    # OR
        ^  # at the start of the line
    )

    [^\[/\n]*+ # all that is not: an opening bracket, a slash or a newline
              # * stands for "0 or more times" and the + after forbids
              # to backtrack in this part if the pattern fails later
              # "*+" is called a "possessive quantifier"
    (?:
        \[                   # literal [
         (?!thing i want\])  # not followed by "thing i want]"
         [^\[/\n]*            
      |                      # OR
         /                   # literal /
         (?!/)               # not followed by an other /
         [^\[/\n]*
     )*+  # zero or more times
) # close the capture group $1
\[thing i want\] # the target

【讨论】:

  • 上面是不是少了2个]?
  • @MDKF:不,但[ 必须在 Java 中的字符类中进行转义。我的错误,现在改正了。
  • 谢谢!它真的很近。我在更换过程中丢失了两个方括号。我是否必须将它们重新插入替换字符串(“$1[best thing ever]”),还是可以更改正则表达式以保留它们?
  • @MDKF:在替换字符串中重新插入它们更简单。
猜你喜欢
  • 1970-01-01
  • 2018-12-18
  • 2017-09-06
  • 1970-01-01
  • 1970-01-01
  • 2011-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多