【问题标题】:Replace a word that is not on a string替换不在字符串中的单词
【发布时间】:2011-10-26 03:31:24
【问题描述】:

我试图替换文件中出现的单词,除非它包含在字符串中:

所以我应该在

中替换this
The test in this line consists in ... 

但不应该匹配:

The test "in this line" consist in ... 

这就是我正在尝试的:

 line.replaceAll( "\\s+this\\s+", " that ")

但在这种情况下它失败了,所以我尝试使用:

 line.replaceAll( "[^\"]\\s+this\\s+", " that ")

但也不行。

任何帮助将不胜感激

【问题讨论】:

  • 那么这个场景中的字符串不包含转义字符?
  • 没错,我应该忽略字符串中的任何内容...

标签: java regex replaceall


【解决方案1】:

这似乎可行(就我从提供的示例中了解您的要求而言):

 (?!.*\s+this\s+.*\")\s+this\s+

http://rubular.com/r/jZvR4XEbRf

您可能需要调整 java 的转义。

其实这样好一点:

 (?!\".*\s+this\s+)(?!\s+this\s+.*\")\s+this\s+

【讨论】:

  • 我相信这被称为负面环顾,不包括符合该条件的字符串。
  • rubular.com/r/Bz9lEasQWT 显示它工作正常,你能提供一个例子吗?我从来没有在 java 中尝试过 2 个负面的环顾四周...
  • 第一次通过但后来失败的确切行:out.println("adding this to other")
  • 这仅适用于每个匹配项在您的测试中位于单独的行上。添加 m 修饰符(因此 . 可以匹配换行符)并且您没有匹配项。有一种方法可以通过前瞻来做到这一点(请参阅我的演示),但我不推荐它。
  • +1 因为这与我认为的正则表达式一样好。但它仍然失败,例如- 这是一个“在”行中的测试 - 正则表达式不是标记引号何时开始和结束的可靠方法。
【解决方案2】:

唯一可靠的方法是搜索完整的引用序列或搜索词。您使用一个正则表达式来执行此操作,并在每次匹配后确定您匹配的是哪一个。如果是搜索词,则替换它;否则你别管它。

这意味着您不能使用replaceAll()。相反,您必须使用 appendReplacement()appendTail() 方法,例如 replaceAll() 本身。这是一个例子:

String s = "Replace this example. Don't replace \"this example.\" Replace this example.";
System.out.println(s);

Pattern p = Pattern.compile("\"[^\"]*\"|(\\bexample\\b)");
Matcher m = p.matcher(s);
StringBuffer sb = new StringBuffer();

while (m.find())
{
  if (m.start(1) != -1)
  {
    m.appendReplacement(sb, "REPLACE");
  }
}
m.appendTail(sb);
System.out.println(sb.toString());

输出:

Replace this example. Don't replace "this example." Replace this example.
Replace this REPLACE. Don't replace "this example." Replace this REPLACE.

See demo online

我假设每个引号都很重要并且它们不能被转义 - 换句话说,您使用的是散文,而不是源代码。可以处理转义引号,但它会使正则表达式变得非常复杂。

如果你真的必须使用replaceAll(),那么一个技巧,你可以使用前瞻来断言匹配后跟有偶数个引号。但它真的很难看,而且对于大文本,您可能会发现它的成本高得令人望而却步,就性能而言。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-03
    • 2014-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多