【问题标题】:Replace all occurences of a word in a string using regex使用正则表达式替换字符串中所有出现的单词
【发布时间】:2013-03-25 03:37:32
【问题描述】:

有没有简单的方法可以替换字符串中所有出现的(整个)单词?我目前正在使用它,它不是很优雅:

public static String replace(String input, String toReplace, 
                           String replacement){
    if(input==null) throw new NullPointerException();
    input = input.replace(" "+toReplace+" ", " "+replacement+" ");
    input = input.replaceAll("^"+toReplace+" ", replacement+" ");
    input = input.replaceAll(" "+toReplace+"$", " "+replacement);
    return input;
}

另外,正则表达式"^"+toReplace+" " 不是正则表达式安全的。例如:当它可能包含 [( 等字符时。

编辑:

这段代码的任何原因:

public static String replace(String input, String toReplace, 
                           String replacement){
    if(input==null) throw new NullPointerException();
    input = input.replace(" "+toReplace+" ", " "+replacement+" ");
    input = input.replaceAll(Pattern.quote("^"+toReplace+" "), replacement+" ");
    input = input.replaceAll(Pattern.quote(" "+toReplace+"$"), " "+replacement);
    //input = input.replaceAll("\\b" + Pattern.quote(toReplace) + "\\b", replacement);
    return input;
}

在以下情况下表现这种方式:

    input = "test a testtest te[(st string test";
    input = replace(input, toReplace, "REP");
    System.out.println(input);

a) toReplace = test 打印:

test a testtest te[(st string test

b)toReplace = te[(st 打印:

test a testtest REP string test

谢谢,

【问题讨论】:

  • 你有什么问题?你的期望是什么?你得到了什么?
  • 我有两个期望:a) 如果我们正则表达式安全,则替换为替换。 b) 代码经济(也许是一行代码)。
  • 正则表达式安全是什么意思?
  • 如果你不想在你的正则表达式模式中允许正则表达式特殊字符,你为什么要使用正则表达式呢?使用用户输入字符串作为正则表达式模式表明您应该重新考虑您的方法。

标签: java regex string replace


【解决方案1】:

使用字边界\bPattern.quote 进行转义。

return input.replaceAll("\\b" + Pattern.quote(toReplace) + "\\b", replacement);

\\b 表示单词和非单词字符之间的零宽度边界,包括字符串的开头和结尾。

【讨论】:

  • 不需要捕获和重写\\b,它们是零长度的。
  • 非捕获?他把它们放在parens中,使它们成为捕获的组。
  • @Keppil 啊,你的意思是零宽度,而不是非捕获。公平点。
  • 谢谢,我有一个附带问题。如果我替换 input = input.replace("^"+toReplace+" ", " "+replacement+" "); with input = input.replace(Pattern.quote("^"+toReplace+" "), " "+replacement+" ");它不适用于测试用例: StringUtils.replace(input, "test", "REP");输入 = 测试一个测试测试 te[(st 字符串。预期输出 = REP 一个测试测试 te[(st 字符串
  • @aryan 你是不是要在那里输入更多内容?
【解决方案2】:

单词边界有一个特殊的正则表达式代码 - \b。这涵盖了您对空格/行尾开头的手动处理以及标点符号等其他情况。

有一个方法Pattern.quote() 引用字符串以保护正则表达式的特殊性,正如您所建议的,如果字符串是任意的或可能是用户提供的,则应始终使用该方法。

这样给出:

input.replaceAll("\\b"+Pattern.quote(toReplace)+"\\b", replacement);

【讨论】:

    【解决方案3】:

    您需要了解正则表达式\b,它是“字边界”的零宽度匹配。有了它,你方法的人就变成了一行:

    return input.replaceAll("\\b"+Pattern.quote(toReplace)+"\\b", replacement);
    

    【讨论】:

      【解决方案4】:
      input = input.replaceAll("\\b"+Pattern.quote(toReplace)+"\\b", replacement);
      

      \b 匹配单词边界,见http://www.regular-expressions.info/wordboundaries.html

      使用 java.util.regex.Pattern.quote 转义特殊字符。

      【讨论】:

      • 代码失败;你必须在你的正则表达式中转义反斜杠。
      • 缺失\已修复。感谢 cmets。
      • 你需要 Pattern.quote(toReplace) 那里。
      • @aryan ...这就是我所说的“使用 java.util.regex.Pattern.quote 转义特殊字符”的意思。 - 但你是对的,它也应该在代码中。
      猜你喜欢
      • 2017-06-23
      • 1970-01-01
      • 1970-01-01
      • 2017-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多