• replace、replaceAll、replaceFirst


     replace、replaceAll、replaceFirst这三个函数会java的同学估计都用过,笔者已经用了2年多,可是,我们真的懂他们吗?

         概述一下他们三个的用法:

              · replace(CharSequence target, CharSequence replacement),用replacement替换所有的target,两个参数都是字符串。

              · replaceAll(String regex, String replacement),用replacement替换所有的regex匹配项,regex很明显是个正则表达式,replacement是字符串。

              · replaceFirst(String regex, String replacement),基本和replaceAll相同,区别是只替换第一个匹配项。

         接下来有个简单的需求,就是把源字符串中的a替换成a,代码如下:

    1 System.out.println("abac".replace("a", "\a")); //abac
    2 System.out.println("abac".replaceAll("a", "\a")); //abac
    3 System.out.println("abac".replaceFirst("a", "\a")); //abac

         结果让人大吃一惊,用了这么多年的替换,竟然有点蒙了。

         源字符串是"abac",然后我们找到"a",把它替换成a,由于是java转义字符,所以想表达a必须写成"\a",第一个反斜线将第二个反斜线转义成普通字符串。

         三个替换表达式,只有第一个replace函数的结果是正确的,问题出在哪呢?

         replaceAll和replaceFirst要求第一个参数是正则表达式,"a"既能理解成字符串a,也可以理解成正则表达式a,所以第一个参数没问题。

         问题就出在第二个参数上,如果读者仔细阅读replaceAll函数的注释,会发现有如下说明:

    Note that backslashes () and dollar signs ($) in the replacement string may cause the results to be different than if it were being treated as a literal replacement string; see Matcher.replaceAll. Use java.util.regex.Matcher.quoteReplacement to suppress the special meaning of these characters, if desired.

         由于replaceAll和replaceFirst的第一个参数是正则,所以我们可以在第二个参数中做些小花样,比如有这样一个需求:把源字符串中的a替换成a后边紧邻的字符,代码如下:

    1 System.out.println("abac".replaceAll("a(\w)", "$1$1")); //bbcc
    2 System.out.println("abac".replaceFirst("a(\w)", "$1$1")); //bbac

         正则的含义假设读者可以读懂,可以看出,在第二个参数中,可以用$符号获取分组的内容,本例中用$1取到了第一个分组的内容,即a后边紧邻的字符。

         因此,$符号在第二个参数中是有特殊含义的,乱写会报错:

    1 System.out.println("abac".replaceAll("a(\w)", "$")); //Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 1

         那假如我就想替换成$呢?这就需要转义字符:

    1 System.out.println("abac".replaceAll("a", "\$")); //$b$c

         到这,读者可能会恍然大悟,原来反斜线在第二个参数中也有特殊含义(转义),所以如果我们想表达反斜线,就必须再转义一次:

    1 System.out.println("abac".replaceAll("a", "\\a")); //abac
    2 System.out.println("abac".replaceFirst("a", "\\a")); //abac

         简单理解一下,"\\a"中前边的反斜线分别转义后边的反斜线,让后边的反斜线就是普通字符串,这样在java内存中看到的字符串就是"\a",然后replaceAll函数在处理时,再用前边的反斜线转义后边的反斜线,来表达后边的反斜线就是普通字符串,不是用来转义$的,最终内存中的字符串就是"a",这样才可以成功将a替换成a。

         转义的问题确实纠结,通过本文,笔者希望读者以后使用这些函数时,能够保持清醒,能够意识到参数中的特殊字符,避免写出定时炸弹。

  • 相关阅读:
    基于设备的回声消除
    Libcurl细说
    抓包分析YY音频
    合唱音效解释
    EXCEL-COUNTIF()统计符合区间上的值个数
    EXCEL-对筛选出(单独手动隐藏行还是在统计范围内)的表格数据进行统计
    Perl字符串处理函数用法集锦
    Selenium-IDE,在网页上模拟人的操作
    Perl哈希%hash
    Perl if条件判断
  • 原文地址:https://www.cnblogs.com/likeju/p/4818241.html
Copyright © 2020-2023  润新知