Java 边界匹配器正则表达式(\b)上的以下代码段出现问题

Java 边界匹配器正则表达式(\b)上的以下代码段出现问题,java,regex,set,Java,Regex,Set,我的意见: 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 me

我的意见:

 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");
        }
    }
}
如果我使用上述代码段,我的输出:(也是我的预期输出)

但是,当我包含更多要删除的单词时,并且出于此目的,当我使用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<String> 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");
    }
}
你们能帮我吗


问题在于您没有创建正确的正则表达式来替换集合中的单词

“\\b”+toDelete+“\\b”
将生成此字符串
\b[结束,某物]\b
,这不是您需要的

要解决此问题,您可以执行以下操作:

for(String del : toDelete){
    line = line.replaceAll("\\b"+del+"\\b", "");
}
这样做的目的是遍历集合,从每个单词中生成一个正则表达式,并从
字符串中删除该单词

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

例如:


这将生成一个类似以下内容的正则表达式:
(\bend\b)|(\bsomething\b)

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

“\\b”+toDelete+“\\b”
将生成此字符串
\b[结束,某物]\b
,这不是您需要的

要解决此问题,您可以执行以下操作:

for(String del : toDelete){
    line = line.replaceAll("\\b"+del+"\\b", "");
}
这样做的目的是遍历集合,从每个单词中生成一个正则表达式,并从
字符串中删除该单词

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

例如:

这将生成一个类似以下内容的正则表达式:
(\bend\b)|(\bsomething\b)

您需要使用

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("");
更新

要允许匹配可能包含特殊字符的整个“单词”,您需要
模式。引用这些单词以转义这些特殊字符,然后需要使用明确的单词边界
(?而不是初始的
\b
,以确保前面和
之间没有单词字符(?!\w)
负前瞻,而不是最后的
\b
,以确保匹配后没有单词char

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

Set<String> nToDel = new HashSet<>();
nToDel = toDelete.stream()
    .map(Pattern::quote)
    .collect(Collectors.toCollection(HashSet::new));
String pattern = "(?<!\\w)(?:" + String.join("|", nToDel) + ")(?!\\w)";
Set nToDel=newhashset();
nToDel=toDelete.stream()
.map(模式::引号)
.collect(Collectors.toCollection(HashSet::new));
String pattern=“(?您需要使用

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("");
更新

要允许匹配可能包含特殊字符的整个“单词”,您需要
模式。引用这些单词以转义这些特殊字符,然后需要使用明确的单词边界
(?而不是初始的
\b
,以确保前面和
之间没有单词字符(?!\w)
负前瞻,而不是最后的
\b
,以确保匹配后没有单词char

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

Set<String> nToDel = new HashSet<>();
nToDel = toDelete.stream()
    .map(Pattern::quote)
    .collect(Collectors.toCollection(HashSet::new));
String pattern = "(?<!\\w)(?:" + String.join("|", nToDel) + ")(?!\\w)";
Set nToDel=newhashset();
nToDel=toDelete.stream()
.map(模式::引号)
.collect(Collectors.toCollection(HashSet::new));

String pattern=“(?谢谢Wiktor。你能建议一种在正则表达式模式中添加括号和特殊字符的方法吗?@venk:你的意思是在
toDelete
项中有非单词(非字母/数字/
)?那么你基于单词边界的方法可能找不到匹配项(如果这些非单词字符出现在开头/结尾,如
\b(?:+end | something-\b
)。您需要在所有项目上运行
模式。引用
,然后使用
(?和
(?!\w)<代码> >而不是<代码> \B/<代码> S.VeNK:请查看更新的答案。请考虑接受它。谢谢您的解决方案。如预期的那样工作:谢谢Wikor。您能建议一种在ReEX模式中添加括号和特殊字符的方法吗?@维克:您的意思是您将拥有非单词吗?(非字母/数字/
\uu
)在
删除
项中?那么基于单词边界的方法可能无法找到匹配项(如果这些非单词字符出现在
\b(?:+end | something-)\b
)。您需要对所有项运行
模式。引用
,然后使用
(?)和
(?!\w)<代码> >而不是<代码> \b/c> S.@ vnk:请参阅更新后的答案。请考虑接受它是否适合您。谢谢您的解决方案。如预期的那样工作:谢谢提图斯。你能建议一种在正则表达式中添加括号和特殊字符的方法吗?@venk你需要使用“`”对这些字符进行转义。你可以找到更多关于这方面的详细信息。谢谢提图斯。你能建议一种在正则表达式中添加括号和特殊字符的方法吗?@venk你需要对这些字符进行转义你可以找到更多关于你在使用Java 8还是Java 7的详细信息?我在使用Java 8你在使用Java 8还是Java 7?我在使用Java 8