9

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

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

我们需要匹配确切的关键字

案例 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

CASE 3 : Keyword & Message with Special Character

如果我收到以下消息并且关键字是#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

请帮忙。

4

5 回答 5

3

案例 2 似乎与案例 3 相反,所以我不认为你可以组合Patterns.

对于案例 2,您Pattern可能看起来像:

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

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

对于案例 3,您Pattern可能看起来像:

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

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

于 2013-08-04T17:17:25.730 回答
3

在正则表达式中使用(?:^|\s)("start of text or whitespace") 代替第一个\b,和(?:$|\s)("end of text or whitespace") 代替第二个\b

于 2013-08-04T17:17:37.220 回答
1

问题来自于“确切词”的定义方式。不仅仅是空格可以包围单词以使其成为单词。例如,在大多数情况下,人们会想要一个与“Hello”完全匹配的单词。

“你好”、“那个年轻人刚刚跟那个年轻人打了声招呼”和“我希望人们在接电话时仍然会说 ahoy 而不是你好。”

如果您希望仅在空格上拆分匹配项,那么我相信您将必须指定空格条件。假设您还希望它在最后匹配,那么我会提出这样的建议。

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[] 并从配置文件加载它们可能会更好。

于 2013-08-04T17:21:09.750 回答
1

试试这种方式

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

(?<=...) 和 (?=...) 是积极的向后和向前看,所以它会在你之前检查是否searchedStubstring

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

此外,如果您想搜索特殊字符,例如$ +和其他字符,您需要转义它们。为此,您可以使用Pattern.quote(searchedStubstring)

于 2013-08-04T17:24:32.973 回答
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 '^' 表示在行首检测字符串,'$' 表示在行尾。在此处查看更多信息: 正则表达式构造摘要

于 2014-04-05T14:12:13.693 回答