Java正则表达式匹配具有特殊字符的精确单词

时间:2013-08-04 17:08:18

标签: java regex string

我有用户输入的关键字列表,它们可能包含$, #, @, ^, &,等特殊字符。

根据我的要求,当我收到短信列表时,我需要搜索每条短信中的所有关键字。

我们需要匹配完全关键字

案例1:简单关键字 - 简单信息

我使用\b来匹配完全关键字, 正常工作

public static void main(String[] args) {
        String patternStr =  "(?i)\\bHello\\b";

        Pattern pattern = Pattern.compile(patternStr);

        List<String> strList = new ArrayList<String>();
        strList.add("HHello Message");
        strList.add("This is Hello Message ");
        strList.add("Now Hellos again.");

        for(String str : strList) {
            Matcher matcher = pattern.matcher(str);
            System.out.println(">> "+matcher.find());
        }
    }

按预期输出

>> false
>> true
>> false

案例2:简单关键字 - 具有特殊字符的消息

现在,如果我为跟踪消息运行相同的代码,那么 无法正常工作

List<String> strList = new ArrayList<String>();
strList.add("#Hello Message");
strList.add("This is Hello Message ");
strList.add("Now Hellos again.");

输出:

true
true
false

预期的输出

false
true
false

案例3:关键字&amp;具有特殊字符的消息

如果我收到以下消息且关键字为#Hello。 我写了以下代码,但无效

public static void main(String[] args) {
        String patternStr =  "(?i)\\b#Hello\\b";

        Pattern pattern = Pattern.compile(patternStr);

        List<String> strList = new ArrayList<String>();
        strList.add("HHello Message");
        strList.add("This is #Hello Message ");
        strList.add("Now Hellos again.");

        for(String str : strList) {
            Matcher matcher = pattern.matcher(str);
            System.out.println(">> "+matcher.find());
        }
    }

输出:

>> false
>> false
>> false

预期的输出:

>> false
>> true
>> false

如何逃避特殊字符并解析 CASE 2 and CASE 3

请帮忙。

5 个答案:

答案 0 :(得分:3)

案例2与案例3相反,所以我认为你不能将Pattern组合起来。

对于案例2,您的Pattern可能如下所示:

Pattern pattern = Pattern.compile("(\\s|^)Hello(\\s|$)", Pattern.CASE_INSENSITIVE);

在这种情况下,我们用空格或输入的开头/结尾包围关键字。

对于案例3,您的Pattern可能如下所示:

Pattern pattern = Pattern.compile("[\\$#@\\^&]Hello(\\s|$)", Pattern.CASE_INSENSITIVE);

在这种情况下,我们在关键字前面加上您选择的任何特殊字符(请注意转义的保留字符$^),然后我们接受空格或输入结束作为关键字后面的字符。

答案 1 :(得分:2)

使用(?:^|\s)(“文字或空格的开头”)代替第一个\b(?:$|\s)(“文字末尾或空格”)而不是第二个{{1}在你的正则表达式中。

答案 2 :(得分:1)

问题来自定义“确切词”的方式。它不仅仅是可以围绕单词的空白,使它成为一个单词。例如,在大多数情况下,人们可能希望使用“Hello”的精确单词匹配。

“你好那里”,“那个年轻人刚刚跟那个年轻人打招呼”和“我希望人们仍然会回答电话,而不是你好。”

如果您希望仅在空格上拆分匹配,那么我相信您必须指定空白条件。假设你也想在最后匹配那么我会建议这样的事情。

Pattern pattern = Pattern.compile("\(^\| \)" + escapeSearchString(patternString) + "\( \|$\)");

然后有几个像这样的方法

public String escapeSearchString(String patternString) {
    StringBuilder stringBuilder = new StringBuilder(patternString.length() * 3);
    for (char c : patternString.toCharArray()) {
        if (isEscapableCharacter(c)) {
            stringBuilder.append("\\");
        }
        stringBuilder.append(c);
    }
}

public boolean isEscapableCharacter(char c) {
    switch (c) {
        case '#':
        case '$':
        case '@':
        case '^':
        case '&':
            return true;
        default:
            return false;
    }
}

对于可转义字符迭代char []并从配置文件加载它们可能会更好。

答案 3 :(得分:1)

尝试这种方式

String patternStr = "(?i)(?<=\\s|^)"+Pattern.quote(searchedStubstring)+"(?=\\s|$)";

(?&lt; = ...)和(?= ...)为正look behind and ahead因此会检查您searchedStubstring之前是否有

  • 空格\\s或之前输入^的开头,以及
  • 空白\\s或其后的输入&的结尾。

如果您想搜索特殊字符,例如$ +和其他人,则需要将其删除。为此,您可以使用Pattern.quote(searchedStubstring)

答案 4 :(得分:0)

例如,如果你的单词想要在开头和结尾有特殊字符(例如这里'#'),你必须写下以下内容:

Pattern p = Pattern.compile("(\\s|^|#)"+word+"(\\s|\\#|$)", Pattern.CASE_INSENSITIVE);

如果你想要完全匹配:

Pattern p = Pattern.compile("(\\s|^)"+word+"(\\s|$)", Pattern.CASE_INSENSITIVE);

带'|'就像OR一样,你可以添加你想要的匹配特殊字符..例如:

Pattern p = Pattern.compile("(\\s|^|#|:|-)"+word+"(\\s|\\#|\\,|\\.|$)", Pattern.CASE_INSENSITIVE);

char'^'表示在行开头检测字符串,'$'表示在行尾。 在这里看到更多: Summary of regular-expression constructs