将整个单词与字符串中的前导或尾随特殊符号(如美元)匹配

Posted

技术标签:

【中文标题】将整个单词与字符串中的前导或尾随特殊符号(如美元)匹配【英文标题】:Matching a whole word with leading or trailing special symbols like dollar in a string 【发布时间】:2018-09-28 01:18:22 【问题描述】:

我可以使用Matcher.quoteReplacement.替换美元符号我可以通过添加边界字符来替换单词:

from = "\\b" + from + "\\b"; 
outString = line.replaceAll(from, to);

但我似乎无法将它们组合起来用美元符号替换单词。

这是一个例子。我正在尝试用“register1”替换“$temp4”(不是$temp40)。

        String line = "add, $temp4, $temp40, 42";
        String to = "register1";
        String from = "$temp4";
        String outString;


        from = Matcher.quoteReplacement(from);
        from = "\\b" + from + "\\b";  //do whole word replacement

        outString = line.replaceAll(from, to);
        System.out.println(outString);

输出

"add, $temp4, $temp40, 42"

如何让它替换 $temp4 并且只替换 $temp4?

【问题讨论】:

【参考方案1】:

Matcher.quoteReplacement() 用于替换字符串 (to),而不是正则表达式 (from)。要在正则表达式中包含字符串文字,请使用 Pattern.quote():

from = Pattern.quote(from);

【讨论】:

@johnktejik 请阅读并理解整个答案。不要只是复制代码并运行。另外,如果方法不清楚,请查看官方文档。另一方面,答案可能从一开始就包含所有信息(以及文档链接)以及完整的代码示例。尽管如此,从某种意义上说,答案是完整的。 @Zabuza 这个答案很有帮助,但不能回答问题。 OP 需要匹配可以以非单词字符开头/结尾的整个单词字符串。 My answer is the solution.【参考方案2】:

$ 在正则表达式中有特殊含义(表示“输入结束”)。要从目标中的字符中删除任何特殊含义,请将其包装在正则表达式引用/取消引用表达式 \Q...\E 中。另外,由于$ 不是“单词”字符,单词边界不会出现,所以请改用环视:

line = line.replaceAll("(?<!\\S)\\Q" + from + "\\E(?![^ ,])", to);

【讨论】:

@john 现在试试 - 我漏掉了 1 个关键字符【参考方案3】:

通常,Pattern.quote 是转义可能被正则表达式引擎特别解释的字符的方法。

但是正则表达式还是不正确,因为line中的$之前没有字边界;空格和$ 都是非单词字符。您需要在$ 字符之后 放置单词边界。这里不需要Pattern.quote,因为你自己在逃避。

String from = "\\$\\btemp4\\b";

或者更简单地说,因为您知道$temp4 之间已经存在单词边界:

String from = "\\$temp4\\b";

from 变量可以从表达式构造来替换。如果from"$temp4",则可以转义美元符号并添加单词边界。

from = "\\" + from + "\\b";

输出:

add, register1, $temp40, 42

【讨论】:

from 是一个变量,因此需要转义的字符的位置甚至存在几乎肯定要到运行时才知道 @Bohemian from 变量可以从要替换的表达式构造,前置"\\$" 并附加"\\b"【参考方案4】:

使用明确的单词边界,(?&lt;!\w)(?!\w),而不是依赖于上下文的 \b

from = "(?<!\\w)" + Pattern.quote(from) + "(?!\\w)";

请参阅regex demo

(?&lt;!\w) 是一个否定的lookbehind,如果在当前位置的左侧有一个非单词字符,则匹配失败;(?!\w) 是一个否定的lookahead,如果有一个非单词字符,则匹配失败char 立即位于当前位置的右侧。 Pattern.quote(from) 是转义 from 变量中的任何特殊字符所必需的。

见Java demo:

String line = "add, $temp4, $temp40, 42";
String to = "register1";
String from = "$temp4";
String outString;

from = "(?<!\\w)" + Pattern.quote(from) + "(?!\\w)";

outString = line.replaceAll(from, to);
System.out.println(outString);
// => add, register1, $temp40, 42

【讨论】:

关于word boundaries 的注释:有资格作为单词边界的三个不同位置: 1) 如果第一个字符是单词字符,则在字符串中的第一个字符之前。 2) 在字符串的最后一个字符之后,如果最后一个字符是单词字符。 3) 字符串中的两个字符之间,一个是单词字符,另一个不是单词字符。* 使用变量时,不能依赖它们。 当然您不需要Matcher.quoteReplacement(from),因为该位未用于替换模式,而是用于正则表达式模式。您需要删除该行,就像我在答案中的代码 sn-p 中那样。

以上是关于将整个单词与字符串中的前导或尾随特殊符号(如美元)匹配的主要内容,如果未能解决你的问题,请参考以下文章

LintCode 53. 翻转字符串

完全匹配,除了前导和尾随特殊字符(包括空格)

第九十四章 SQL函数 %MINUS

需要正则表达式匹配最多8位的int,包括,前导或尾随0但不是单个数字“0”[关闭]

用字符串方法计算单词?

如何删除前导和尾随的空格以及字符串中的多个空格? [复制]