你能帮我找到一个带有短语列表的正则表达式,并检查给定文本中是否存在其中一个短语吗?
示例:
如果我在hashSet
中有以下字词:
كيف الحال
إلى أين
أين يوجد
هل من أحد هنا
给定的文字是:كيف الحال أتمنى أن تكون بخير
我想在执行正则表达式之后得到:كيف الحال
我的初始代码:
HashSet<String> QWWords = new HashSet<String>();
QWWords.add("كيف الحال");
QWWords.add("إلى أين");
QWWords.add("أين يوجد");
QWWords.add("هل من أحد هنا");
String s1 = "كيف الحال أتمنى أن تكون بخير";
for (String qp : QWWords) {
Pattern p = Pattern.compile("[\\s" + qp + "\\s]");
Matcher m = p.matcher(s1);
String found = "";
while (m.find()) {
found = m.group();
System.out.println(found);
}
}
答案 0 :(得分:4)
[...]
是character class,字符类只能匹配它指定的一个字符。例如,[abc]
之类的字符类只能匹配a
OR b
或c
。因此,如果您只想找到单词abc
,请不要使用[...]
将其包围。
另一个问题是您使用\\s
作为单词分隔符,因此在跟随字符串
String data = "foo foo foo foo";
正则表达式\\sfoo\\s
将无法与第一个foo
匹配,因为 之前没有空格。
所以首先匹配它会发现
String data = "foo foo foo foo";
// this one--^^^^^
现在,由于正则表达式在第二个foo
之后消耗了空间,因此无法在下一个匹配中重复使用它,因此也会跳过第三个foo
,因为在它之前没有可用空间匹配。
您也不会匹配foo
,因为这次之后没有空格。
要解决此问题,您可以使用\\b
- word boundary检查它所代表的位置是否在字母数字和非字母数字字符之间(或字符串的开头/结尾)。
所以而不是
Pattern p = Pattern.compile("[\\s" + qp + "\\s]");
使用
Pattern p = Pattern.compile("\\b" + qp + "\\b");
或者可能更好Tim mentioned
Pattern p = Pattern.compile("\\b" + qp + "\\b",Pattern.UNICODE_CHARACTER_CLASS);
确保\\b
在预定义的字母数字类中包含阿拉伯字符。
更新:
我不确定您的字词是否可以包含{
[
+
*
等正则表达式元字符,以防万一您也可以添加转义机制将这些字符更改为文字。
所以
"\\b" + qp + "\\b"
可以成为
"\\b" + Pattern.quote(qp) + "\\b"