Java正则表达式在ascii范围之外不匹配,其行为与python正则表达式不同
我想用sklearn的方法过滤文档中的字符串。它使用以下正则表达式:Java正则表达式在ascii范围之外不匹配,其行为与python正则表达式不同,java,regex,scikit-learn,pattern-matching,countvectorizer,Java,Regex,Scikit Learn,Pattern Matching,Countvectorizer,我想用sklearn的方法过滤文档中的字符串。它使用以下正则表达式:(?u)\b\w\w+\b。 此java代码的行为方式应相同: Pattern regex = Pattern.compile("(?u)\\b\\w\\w+\\b"); Matcher matcher = regex.matcher("this is the document.!? äöa m²"); while(matcher.find()) { String match = matcher.group();
(?u)\b\w\w+\b
。
此java代码的行为方式应相同:
Pattern regex = Pattern.compile("(?u)\\b\\w\\w+\\b");
Matcher matcher = regex.matcher("this is the document.!? äöa m²");
while(matcher.find()) {
String match = matcher.group();
System.out.println(match);
}
但这不会像python中那样产生所需的输出:
this
is
the
document
äöa
m²
它反而输出:
this
is
the
document
我该怎么做才能像python正则表达式那样包含非ascii字符呢?还有一步要做:您需要指定
\w
也包含unicode字符<代码>模式。UNICODE\u字符\u类用于救援:
Pattern regex = Pattern.compile("(?u)\\b\\w\\w+\\b", Pattern.UNICODE_CHARACTER_CLASS);
// ^^^^^^^^^^
Matcher matcher = regex.matcher("this is the document.!? äöa m²");
while(matcher.find()) {
String match = matcher.group();
System.out.println(match);
}
正如Wiktor在评论中所建议的,您可以使用
(?U)
打开标志UNICODE\U CHARACTER\U CLASS
。虽然这允许匹配äöa
,但仍然不匹配m²
。这是因为带有\w
的UNICODE\u CHARACTER\u类
无法将²
识别为有效的字母数字字符。作为\w
的替代品,您可以使用[\pN\pL\u]
。这与Unicode数字\pN
和Unicode字母\pL
(加上\uu
)匹配。Unicode字符类包括\pNo
字符类,其中包括拉丁语1增补-拉丁语1标点符号和符号字符类(包括字符类)。或者,您可以将\pNo
Unicode字符类添加到具有\w
的字符类中。这意味着以下正则表达式与字符串正确匹配:
[\pN\pL_]{2,} # Matches any Unicode number or letter, and underscore
(?U)[\w\pNo]{2,} # Uses UNICODE_CHARACTER_CLASS so that \w matches Unicode.
# Adds \pNo to additionally match ²³¹
那么为什么Java中的\w
不匹配²
,而Python中却匹配
Java的解释
查看,我们得到以下信息(我删除了与回答问题无关的信息):
Unicode支持
以下预定义字符类和POSIX字符
等级符合附录C的建议:
Unicode正则表达式的兼容性属性,当
指定了UNICODE字符类
标志
\w
一个单词字符:[\p{Alpha}\p{gc=Mn}\p{gc=Me}\p{gc=Mc}\p{Digit}\p{gc=Pc}\p{IsJoin\u Control}]
太好了!现在,当使用(?U)
标志时,我们有了\w
的定义。将这些Unicode字符类插入将准确地告诉您每个Unicode字符类匹配的内容。在不把这篇文章写得太长的情况下,我将继续告诉您以下两个类都不匹配²
:
\p{Alpha}
\p{gc=Mn}
\p{gc=Me}
\p{gc=Mc}
\p{Digit}
\p{gc=Pc}
\p{IsJoin\u Control}
Python的解释 那么,当
u
标志与\w
一起使用时,为什么Python会匹配u
?这一个很难找到,但我开始深入研究。在消除了许多关于如何调用此函数的漏洞之后,基本上会发生以下情况:
定义为\w
,然后在前面加上CATEGORY\u UNI\u WORD
SRE
callsSRE\u分类统一词
SRE\u统一词(ch)
被定义为SRE_UNI_IS_WORD
)(SRE_UNI_IS_ALNUM(ch)| |(ch)==''.'''.'
调用SRE_UNI_IS_ALNUM
,它又被定义为Py_UNICODE_ISALNUM
(Py_UNICODE_ISALPHA(ch)| Py_UNICODE_ISDECIMAL(ch)| Py_UNICODE_ISDIGIT(ch)| Py||UNICODE_ISDIGIT(ch))
- 这里重要的是
,定义为Py\u UNICODE\u ISDECIMAL(ch)
Py\u UNICODE\u ISDECIMAL(ch)\u PyUnicode\u isdecimaldigital(ch)
现在,让我们看看方法>代码> 很好,因此基本上,如果字符的UTF-32编码字节具有
DECIMAL\u MASK
标志,这将计算为true,并返回大于或等于0
的值
的UTF-32编码字节值是0x000000b2
,我们的标志十进制掩码是0x02
0x000000b2&0x02
的计算结果为true,因此在python中被视为有效的Unicode字母数字字符,因此\w
与u
标志匹配²Try“(?u)\\b\\w\\w+\\b”
或仅匹配”(?u)\\w{2,}”
@WiktorStribiżew对äöa
有效,但对m²无效
这可能有用吗?非常感谢。这适用于德语字母,但仍然不包括平方号(²),知道如何修复它吗?@LanceToth我使用的是Java,不是JavaScript
int _PyUnicode_IsDecimalDigit(Py_UCS4 ch)
{
if (_PyUnicode_ToDecimalDigit(ch) < 0)
return 0;
return 1;
}
int _PyUnicode_ToDecimalDigit(Py_UCS4 ch)
{
const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
return (ctype->flags & DECIMAL_MASK) ? ctype->decimal : -1;
}