使用Matcher类替换字符串 -- 《JAVA编程思想》43

在实际业务开发中,对字符串进行替换是常常遇到的场景,通常可以使用以下三种方式:

(1) replace(CharSequence target, CharSequence replacement)

通过 replace() 方法指定需要替换的新老字符执行替换操作,此方法还有个支持 char 类型的重载方法 replace(char oldChar, char newChar) 。

        String str = "a1 b2 c3 d4 e5";
        System.out.println(str.replace('a', 'A'));
        System.out.println(str.replace("b2", "B2"));
A1 b2 c3 d4 e5
a1 B2 c3 d4 e5

(2) replaceFirst(String regex,String replacement)

通过 replaceFirst() 将满足正则表达式的第一个字符串进行替换

        String str = "a1 b2 c3 d4 e5";
        System.out.println(str.replaceFirst("[a-z][0-9]", "value"));
value b2 c3 d4 e5

(3) replaceAll(String regex, String replacement)

通过 replaceAll() 将满足正则表达式的全部字符串进行替换

        String str = "a1 b2 c3 d4 e5";
        System.out.println(str.replaceAll("[a-z]", "value"));
value1 value2 value3 value4 value5

上述三种方法只能满足简单的替换要求,假设现在需要将字符串中的空格去除,还需要将指定字母全部转成大写,这时就需要使用到 Matcher类。

首先,我们来了解 Matcher 类中的几个方法:

(1) appendReplacement(StringBuffer sb, String replacement)

将这次匹配到字符串替换为 replacement ,并获取上一次匹配至这一次匹配之间的字符串,追加 replacement 至它们之后,再存入 StringBuffer 中。

(2)appendTail(StringBuffer sb)

将最后一次匹配之后的字符串存入 StringBuffer 中。

上述两个方法初看难以理解,可以结合下例进行消化:

public class TheReplacements {
    
    

    public static String s = "/*!  Here's  a  block  of  text  to  use  as  input  to\n" +
            "  the  regular  expression  matcher.  Note  that  we'll\n" +
            "  first  extract  the  block  of  text  by  looking  for\n" +
            "  the  special  delimiters,  then  process  the\n" +
            "  extracted  block.  !*/";

    public static void main(String[] args) {
    
    
        System.out.println("---初始值---");
        System.out.println(s);
        Matcher mInput = Pattern.compile("/\\*!(.*)!\\*/", Pattern.DOTALL).matcher(s);
        if (mInput.find()) {
    
    
            s = mInput.group(1);
            System.out.println("---去除行首的空格并将2个以上的空格变为1个空格---");
            s = s.replaceAll(" {2,}", " ");
            s = s.replaceAll("(?m)^ +", "");
            System.out.println(s);
            s = s.replaceFirst("[aeiou]", "(VOWEL1)");
            StringBuffer buffer = new StringBuffer();
            Pattern p = Pattern.compile("[aeiou]");
            Matcher m = p.matcher(s);
            while (m.find()) {
    
    
                m.appendReplacement(buffer, m.group().toUpperCase());
            }
            m.appendTail(buffer);
            System.out.println("---将首个元音字母变为VOWEL1,其余元音字母变为大写,并打印最终字符串---");
            System.out.println(buffer);
        }
    }

}
---初始值---
/*!  Here's  a  block  of  text  to  use  as  input  to
  the  regular  expression  matcher.  Note  that  we'll
  first  extract  the  block  of  text  by  looking  for
  the  special  delimiters,  then  process  the
  extracted  block.  !*/
---去除行首的空格并将2个以上的空格变为1个空格---
Here's a block of text to use as input to
the regular expression matcher. Note that we'll
first extract the block of text by looking for
the special delimiters, then process the
extracted block. 
---将首个元音字母变为VOWEL1,其余元音字母变为大写,并打印最终字符串---
H(VOWEL1)rE's A blOck Of tExt tO UsE As InpUt tO
thE rEgUlAr ExprEssIOn mAtchEr. NOtE thAt wE'll
fIrst ExtrAct thE blOck Of tExt by lOOkIng fOr
thE spEcIAl dElImItErs, thEn prOcEss thE
ExtrActEd blOck. 

Process finished with exit code 0

上述代码第一步通过正则表达式/\*!(.*)!\*/获取 /*!!*/之间的字符串,并制定匹配模式为 Pattern.DOTALL ,符号 . 可以匹配换行符 \n ,故最终可以匹配整个字符串,否则默认匹配第一行(关于正则表达式匹配模式的介绍可以参考Pattern的多种匹配模式)。

之后再将字符串中的2个以上的空格,全部替换为一个空格

  s = s.replaceAll(" {2,}", " ");

将每行第一个空格去除,?m 代表正则表达式开启多行匹配模式,否则只会匹配第一行。

  s = s.replaceAll("(?m)^ +", "");

将第一个元音字母替换为 VOWEL1

s.replaceFirst("[aeiou]", "(VOWEL1)");

执行为常规的替换之后,就是 Matcher 类出场了,m 依次匹配所有的元音字母,并将每个元音字母替换为大写,再将替换结果存入 StringBuffer 中,最后在通过 appendTail() 将未匹配上的字符串追加至 StringBuffer 中。

这里打印一部分 appendReplacement() 依次执行的结果,方便大家理解。

            while (m.find()) {
    
    
                m.appendReplacement(buffer, m.group().toUpperCase());
                System.out.println(buffer);
            }
H(VOWEL1)rE
H(VOWEL1)rE's A
H(VOWEL1)rE's A blO
H(VOWEL1)rE's A blOck O
H(VOWEL1)rE's A blOck Of tE
H(VOWEL1)rE's A blOck Of tExt tO
H(VOWEL1)rE's A blOck Of tExt tO U
H(VOWEL1)rE's A blOck Of tExt tO UsE
H(VOWEL1)rE's A blOck Of tExt tO UsE A
H(VOWEL1)rE's A blOck Of tExt tO UsE As I
H(VOWEL1)rE's A blOck Of tExt tO UsE As InpU
H(VOWEL1)rE's A blOck Of tExt tO UsE As InpUt tO
H(VOWEL1)rE's A blOck Of tExt tO UsE As InpUt tO

如果对 Matcher 类中 find() 、group() 尚不了解的,可以参考Matche类在正则表达式中的应用

本次分享至此结束,希望本文对你有所帮助,若能点亮下方的点赞按钮,在下感激不尽,谢谢您的【精神支持】。

若有任何疑问,也欢迎与我交流,若存在不足之处,也欢迎各位指正!

Guess you like

Origin blog.csdn.net/BaymaxCS/article/details/119275151