边界匹配器正则表达式(\ 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)