边界匹配器正则表达式(\ b)下面的代码片段问题

我的意见:

1. end 2. end of the day or end of the week 3. endline 4. something 5. "something" end 

基于上述讨论,如果我尝试使用此代码段替换单个字符串,它会成功删除该行中的相应单词

 public class DeleteTest { public static void main(String[] args) { // TODO Auto-generated method stub try { File file = new File("C:/Java samples/myfile.txt"); File temp = File.createTempFile("myfile1", ".txt", file.getParentFile()); String delete="end"; BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file))); PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(temp))); for (String line; (line = reader.readLine()) != null;) { line = line.replaceAll("\\b"+delete+"\\b", ""); writer.println(line); } reader.close(); writer.close(); } catch (Exception e) { System.out.println("Something went Wrong"); } } } 

我的输出如果我使用上面的代码片段:(也是我的预期输出)

  1. 2. of the day or of the week 3. endline 4. something 5. "something" 

但是当我包含更多要删除的单词时,为了这个目的,当我使用Set时,我使用下面的代码片段:

 public static void main(String[] args) { // TODO Auto-generated method stub try { File file = new File("C:/Java samples/myfile.txt"); File temp = File.createTempFile("myfile1", ".txt", file.getParentFile()); BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file))); PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(temp))); Set toDelete = new HashSet(); toDelete.add("end"); toDelete.add("something"); for (String line; (line = reader.readLine()) != null;) { line = line.replaceAll("\\b"+toDelete+"\\b", ""); writer.println(line); } reader.close(); writer.close(); } catch (Exception e) { System.out.println("Something went Wrong"); } } 

我得到我的输出:(它只是删除空格)

  1. end 2. endofthedayorendoftheweek 3. endline 4. something 5. "something" end 

你能帮助我吗?

点击这里关注该主题

您需要使用该创建一个替换组

 String.join("|", toDelete) 

并用作

 line = line.replaceAll("\\b(?:"+String.join("|", toDelete)+")\\b", ""); 

图案看起来像

 \b(?:end|something)\b 

请参阅正则表达式演示 。 这里, (?:...)是一个非捕获组,用于对几个备选项进行分组而不为捕获创建内存缓冲区(因为删除匹配项后不需要它)。

或者,更好的是,在进入循环之前编译正则表达式:

 Pattern pat = Pattern.compile("\\b(?:" + String.join("|", toDelete) + ")\\b"); ... line = pat.matcher(line).replaceAll(""); 

更新

为了允许匹配可能包含特殊字符的整个“单词”,你需要Pattern.quote那些单词来逃避那些特殊的字符,然后你需要使用明确的单词边界, (?而不是初始的\b确保之前没有单词char和(?!\w)否定前瞻而不是最终\b以确保匹配后没有单词char。

在Java 8中,您可以使用以下代码:

 Set nToDel = new HashSet<>(); nToDel = toDelete.stream() .map(Pattern::quote) .collect(Collectors.toCollection(HashSet::new)); String pattern = "(? 

正则表达式看起来像(? 。 请注意, \Q\E之间的符号被解析为文字符号

问题是你没有创建正确的正则表达式来替换集合中的单词。

"\\b"+toDelete+"\\b"将产生这个String \b[end, something]\b ,这不是你需要的。

要解决这个问题,你可以这样做:

 for(String del : toDelete){ line = line.replaceAll("\\b"+del+"\\b", ""); } 

这样做是通过集合,从每个单词生成一个正则表达式并从line字符串中删除该单词。

另一种方法是从集合中的所有单词生成单个正则表达式。

例如:

 String regex = ""; for(String word : toDelete){ regex+=(regex.isEmpty() ? "" : "|") + "(\\b"+word+"\\b)"; } .... line = line.replace(regex, ""); 

这应该产生一个如下所示的正则表达式: (\bend\b)|(\bsomething\b)