在我们开始替换文本的时候,正则表达式就变得尤为有用了。下面是一些可用的方法:
replaceFirst(Stringreplacement)用 replacement 替换输入字符串中最先匹配的那部
分。
replaceAll(Stringreplacement)用 replacement 替换输入字符串中所有的匹配部分。
appendReplacement(StringBuffersbuf, String replacement)逐步地在 sbuf 中执行
替换,而不是像replaceFirst( )那样仅替换第一个匹配或者像 replaceAll( )是替换所有的
匹配。这是个非常重要的方法,因为它允许我们通过调用某些方法并执行一些其他处理来产
生 replacement(而 replaceFirst()和 replaceAll( )只能输入固定字符串)。有了这
个方法,我们就可以通过编程来实现将目标拆分成组以及创建功能强大的替换。
appendTail(StringBuffer sbuf, String replacement) 在一个或多个
appendReplacement()调用之后被调用,以便复制输入字符串的剩余部分。
下面这个例子展示了所有的替换操作。另外,开始部分的注释文本块被提取了出来,并用正
则表达式对其进行处理,以便将其用作该例子其他部分的输入。
//: c12:TheReplacements.java
importjava.util.regex.*;
importjava.io.*;
importcom.bruceeckel.util.*;
importcom.bruceeckel.simpletest.*;
/*! Here's ablock of text to use as input to
the regular expression matcher. Notethat we'll
first extract the block of text bylooking for
the special delimiters, then processthe
extracted block. !*/
public classTheReplacements {
private static Test monitor = new Test();
public static void main(String[] args)throws Exception {
String s =TextFile.read("TheReplacements.java");
// Match the specially-commented blockof text above:
Matcher mInput =
Pattern.compile("/\\*!(.*)!\\*/", Pattern.DOTALL)
.matcher(s);
if(mInput.find())
s = mInput.group(1); // Captured byparentheses
// Replace two or more spaces with asingle space:
s = s.replaceAll(" {2,}"," ");
// Replace one or more spaces at thebeginning of each
// line with no spaces. Must enableMULTILINE mode:
s = s.replaceAll("(?m)^ +","");
System.out.println(s);
s = s.replaceFirst("[aeiou]","(VOWEL1)");
StringBuffer sbuf = new StringBuffer();
Pattern p =Pattern.compile("[aeiou]");
Matcher m = p.matcher(s);
// Process the find information as you
// perform the replacements:
while(m.find())
m.appendReplacement(sbuf,m.group().toUpperCase());
// Put in the remainder of the text:
m.appendTail(sbuf);
System.out.println(sbuf);
monitor.expect(new String[]{
"Here's a block of text to useas input to",
"the regular expressionmatcher. Note that we'll",
"first extract the block oftext by looking for",
"the special delimiters, thenprocess the",
"extracted block. ",
"H(VOWEL1)rE's A blOck Of tExttO UsE As InpUt tO",
"thE rEgUlAr ExprEssIOn mAtchEr.NOtE thAt wE'll",
"fIrst ExtrAct thE blOck OftExt by lOOkIng fOr",
"thE spEcIAl dElImItErs, thEn prOcEssthE",
"ExtrActEd blOck. "
});
}
} ///:~
上面的例子打开了文件并使用本章前面介绍的 TextFile.read( )方法对其进行读取。创建了
mInput 用以匹配在‘/*!’ 和 ‘!*/’之间的所有文本(注意分组的圆括号)。然后,多于两个
的空格被减缩成一个,并且每行开始的所有空格都被删掉(为了对所有的行而不仅是输入的
开始部分都能这样处理,必须使用多行模式)。这两个替换都是用等价的 replaceAll( )来执
行的(在这种情形下,显得更方便)。注意既然每个替换在程序中只能被使用一次,因此这
样做与把它作为一个模式进行预先编译相比,不会有任何额外的花费。
replaceFirst( )仅对找到的第一个匹配进行替换。另外, replaceFirst( )和 replaceAll( )
中的替换字符串仅是字面意义上的,因此如果我们想在每个替换上执行一些操作,它们就不
会有太大帮助。如果确实要那样的话,我们需要使用 appendReplacement( ),它可以让
我们将任意数量的代码编写进执行替换的过程。在前一个例子中,选择 group( )然后进行
处理——在这种情形下,将正则表达式发现的元音字母设置为大写——作为正在创建的
sbuf 的结果。通常地,我们会逐步地执行所有替换,然后调用 appendTail( ),但是如果
我们想模仿replaceFirst( )(或者“替换第 n 个“),我们仅需要执行一次替换,然后调用
appendTail( )把剩余部分输入到 sbuf 即可。
appendReplacement()也可以让我们通过用“$g”(其中‘g’是组号)的形式,来在替代字
符串中直接引用被捕获的组。然而,这只适合于较为简单的处理,并且它不会在前面的程序
中产生你所期望的结果。