如何在Java中编写一个正则表达式,它将对不在注释中的组执行.replaceFirst?

Jas*_*son 0 java regex regex-lookarounds

所以我需要返回修改后的String,它在跳过注释时用另一个标记替换标记的第一个实例.这是我正在谈论的一个例子:

This whole quote is one big String
-- I don't want to replace this @@
But I want to replace this @@!
Run Code Online (Sandbox Code Playgroud)

作为一名前.NET开发人员,我认为这很容易.我只是像这样做一个负面的观察:

(?<!--.*)@@
Run Code Online (Sandbox Code Playgroud)

但后来我学会了Java无法做到这一点.所以在得知花括号没问题后,我尝试了这个:

(?<!--.{0,9001})@@
Run Code Online (Sandbox Code Playgroud)

这并没有引发异常,但它确实与评论中的@@相匹配.

当我用Java正则表达式测试器测试这个正则表达式时,它按预期工作.关于我唯一能想到的是我使用的是Java 1.5.Java 1.5是否有可能在其正则表达式引擎中出现错误?假设它确实如此,我如何让Java 1.5做我想做的事情而不分解我的字符串并重新组装它?

编辑我将#更改为 - 运算符,因为看起来正则表达式会更复杂,有两个字符而不是一个字符.我最初没有透露我正在修改一个查询,以避免关于"那么你不应该那样修改查询!"的主题讨论.我有一个很好的理由这样做.请不要讨论查询修改的良好做法.谢谢

Roh*_*ain 5

你真的不需要negative look-behind这里.你也可以不用这样做.

它会是这样的:

String str = "I don't want to replace this @@";     
str = str.replaceAll("^([^#].*?)@@", "$1");
Run Code Online (Sandbox Code Playgroud)

因此,它取代了之前不以字符串部分@@开头的字符串中的第一次出现.所以,删除.这是有效的,因为它使用了一个不情愿的量词 - .所以,它会在第一次自动停止.#@@@@replaceAll.*?@@


正如@nhahtdh在评论中正确指出的那样,如果您的评论位于该行的末尾,则可能会失败.所以,你可以使用这个:

String str = "I don't want to # replace this @@";
str = str.replaceAll("^([^#]*?)@@", "$1");
Run Code Online (Sandbox Code Playgroud)

这个适用于任何情况.在给定的示例中,它不会替换@@,因为它是注释的一部分.


如果您的注释开始由两个字符表示,则否定的字符类将不起作用.你需要这样使用negative look-ahead:

String str = "This whole quote @@  is one big String -- asdf @@\n" +
             "-- I don't want to replace this @@\n" + 
             "But I want to replace this @@!";
str = str.replaceAll("(?m)^(((?!--).)*?)@@", "$1");

System.out.println(str);
Run Code Online (Sandbox Code Playgroud)

输出:

This whole quote   is one big String -- asdf @@
-- I don't want to replace this @@
But I want to replace this !
Run Code Online (Sandbox Code Playgroud)

(?m)在模式的开头用于启用MULTILINE匹配模式,因此^将匹配每一行的开头,而不是整个表达式的开头.