如何使用正则表达式替换部分字符串

时间:2010-09-24 14:02:26

标签: java

我不是正则表达式的初学者,但它们在perl中的使用似乎与Java有点不同。

无论如何,我基本上都有一个速记词及其定义的字典。我想迭代字典中的单词并用它们的含义替换它们。在JAVA中这样做的最佳方式是什么?

我见过String.replaceAll(),String.replace()以及Pattern / Matcher类。我希望按照以下方式进行不区分大小写的替换:

word =~ s/\s?\Q$short_word\E\s?/ \Q$short_def\E /sig

虽然我在这里,你认为最好从字符串中提取所有单词,然后应用我的字典或只是将字典应用到字符串?我知道我需要小心,因为简写的单词可以与其他简写含义相匹配。

希望这一切都有道理。

感谢。

澄清:

字典就像: lol:大声笑出声,rofl:在地板上滚动着笑,ll:喜欢柠檬

字符串是: 大声笑,我是rofl

替换文字: 大声笑,我在地板上笑着滚动

注意ll没有添加到任何地方

3 个答案:

答案 0 :(得分:2)

危险是正常词语中的误报。 “跌倒”!=“felikes lemons”

一种方法是在空格上拆分单词(需要保存多个空格吗?)然后在List上执行上面的'if contains(){replace} else {output original}想法。

我的输出类是StringBuffer

StringBuffer outputBuffer = new StringBuffer();
for(String s: split(inputText)) {
   outputBuffer.append(  dictionary.contains(s) ? dictionary.get(s) : s); 
   }

让你的分割方法足够聪明,还可以返回单词分隔符:

split("now is the  time") -> now,<space>,is,<space>,the,<space><space>,time

然后你不必担心保留空格 - 上面的循环只会将不是字典单词的任何内容附加到StringBuffer。

这是retaining delimiters when regexing上最近的SO帖子。

答案 1 :(得分:2)

如果您坚持使用正则表达式,这将起作用(采用Zoltan Balazs的字典映射方法):

Map<String, String> substitutions = loadDictionaryFromSomewhere();
int lengthOfShortestKeyInMap = 3; //Calculate
int lengthOfLongestKeyInMap = 3; //Calculate

StringBuffer output = new StringBuffer(input.length());
Pattern pattern = Pattern.compile("\\b(\\w{" + lengthOfShortestKeyInMap + "," + lengthOfLongestKeyInMap + "})\\b");
Matcher matcher = pattern.matcher(input);
while (matcher.find()) {
    String candidate = matcher.group(1);
    String substitute = substitutions.get(candidate);
    if (substitute == null)
        substitute = candidate; // no match, use original
    matcher.appendReplacement(output, Matcher.quoteReplacement(substitute));
}
matcher.appendTail(output);
// output now contains the text with substituted words

如果您计划处理多个输入,预先编译模式比使用String.split()更有效,Pattern每次调用都会编译一个新的Pattern pattern = Pattern.compile("\\b(lol|rtfm|rofl|wtf)\\b"); // rest of the method unchanged, don't need the shortest/longest key stuff

(编辑)将所有键编译成单个模式会产生更有效的方法,如下所示:

{{1}}

这允许正则表达式引擎跳过任何恰好足够短但不在列表中的单词,从而为您节省大量的地图访问权。

答案 2 :(得分:1)

首先,我想到的是:

...
// eg: lol -> laugh out loud
Map<String, String> dictionatry;

ArrayList<String> originalText;
ArrayList<String> replacedText;

for(String string : originalText) {
   if(dictionary.contains(string)) {
      replacedText.add(dictionary.get(string));
   } else {
      replacedText.add(string);
   }
...

或者您可以使用StringBuffer而不是replacedText