posts - 8,  comments - 6,  trackbacks - 0

2.5  使用正则表达式进行替换

在上一节中,介绍了用于匹配一个String中的模式和用于从一个子模式组中检索数据的正则表达式。使用regex,还可以用新的值替代匹配的模式。完成此操作的一种方法是使用Matcher类的replaceAll方法,它将返回一个字符串,将所有匹配的子串替换为给定的字符串。为了说明此方法,查找一个文件内出现的所有repetition单词并使用单词duplication来替换它们:
String data = getStringData();
Pattern repPattern = Pattern.compile("(\\s)(repetition)([\\s;\\.,])");
Matcher repMatcher = repPattern.matcher(data);
String newData = repMatcher.replaceAll("$1duplication$3");

为了查找单词,需要捕获它前后的空白(或标点符号)。需要注意的是,如果此单词出现在data字符串的开头,那么上述的代码不会匹配它,因为已假定它的前后存在空白符。除了单词repetition被替换外,我们希望文本中的其他内容与原始文本保持一致,包括单词周围的空白字符。这里的美元符号($)显然不表示货币。它表示对从regex模式中捕获的组1和组3的逆向引用,包含最初匹配的空白或标点符号。这样,与它们对应的值将插入到替换文本中。

String类(在JDK 1.4或更高的版本中)有一个replaceAll方法,其工作机制类似于Matcher中的replaceAll方法。这使得它可以很方便地替换一个与模式匹配的子串:

String data = getStringData();
String result =
data.replaceAll("(\\s)(repetition)([\\s;\\.,])", "$1duplication$3");

replaceAll方法返回一个新的字符串,其中所有匹配的部分已被新值替换。但是,使用Matcher仍有很多优点,因为相对于字符串它有更大的灵活性。

可以使用Matcher的find循环用新值依次替换每个匹配的部分。这样使你能够更好地控制替换过程。比如,可以在每次匹配的过程中应用其他逻辑,甚至每次可以替换不同的值。这就用到了StringBuffer,StringBuffer用于保存更新的文本,并且一旦调用appendReplacement方法,Matcher就追加更新后的文本到缓存中。在处理每个匹配并执行替换后,需要使用appendTail方法将最后一次匹配后的剩余字符串放置在输出缓存中。图2-1说明了子串匹配和这两种方法之间的关系。

图2-1  Matcher类的append方法 
Matcher有一个相应的append指针。指针最初从零开始,随着每次调用appendReplacement向前移动。这种设计是为了在一个find循环内使用它。每次匹配后,调用appendReplacement方法,Matcher将指针所在的上一个位置到匹配之前指针所在的位置之间的内容,即未更改的文本合并到StringBuffer中。然后,Matcher替换当前匹配的文本并将替换后的内容放置在StringBuffer中。接下来,Matcher将append指针移动到当前匹配结尾之后的第一个字符,然后重复此过程直到不再产生匹配。在找到所有匹配之后很可能剩下一个未匹配的部分。为了将这部分文本添加到输出StringBuffer中,使用appendTail方法。
现在使用这些方法将前面的替换例子重写为一个循环。但是这一次对于每个匹配,将使用一个随机选择的同义词(repetition、duplication、copying、reiteration、recurrence或redundancy)来替代单词repetition:
StringBuffer result = new StringBuffer();
String[] wordChoices = new String[]
{"repetition", "duplication", "copying",
"reiteration", "recurrence", "redundancy"};
Random rand = new Random();
String data = getStringData();
Pattern repPattern = Pattern.compile("(\\s)(repetition)([\\s;\\.,])");
Matcher repMatcher = repPattern.matcher(data);
while (repMatcher.find()) {
// pick a word at random
int wordIndex = rand.nextInt(wordChoices.length);
String replacement = "$1" + wordChoices[wordIndex] + "$3";
repMatcher.appendReplacement(result, replacement);
}
repMatcher.appendTail(result);
System.out.println(result);

可以按需求改写find循环中的逻辑来对每个匹配进行所需的处理。此外,还可以使用前面讨论过的Matcher的方法:group、start和end。可以使用这些技术的组合有选择地修改或删除一个文件中每部分匹配的文本。

只有注册用户登录后才能发表评论。


网站导航:
 

<2024年12月>
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

留言簿(1)

随笔分类

随笔档案

文章分类

文章档案

搜索

  •  

最新评论

阅读排行榜