问题
There are many questions and answers here on StackOverflow that assume a "letter" can be matched in a regexp by [a-zA-Z]
. However with Unicode there are many more characters that most people would regard as a letter (all the Greek letters, Cyrllic .. and many more. Unicode defines many blocks each of which may have "letters".
The Java definition defines Posix classes for things like alpha characters, but that is specified to only work with US-ASCII. The predefined character classes define words to consist of [a-zA-Z_0-9]
, which also excludes many letters.
So how do you properly match against Unicode strings? Is there some other library that gets this right?
回答1:
Here you have a very nice explanation:
http://www.regular-expressions.info/unicode.html
Some hints:
"Java and .NET unfortunately do not support \X
(yet). Use \P{M}\p{M}*
as a substitute. To match any number of graphemes, use (?:\P{M}\p{M}*)+
instead of \X+
."
"In Java, the regex token \uFFFF
only matches the specified code point, even when you turned on canonical equivalence. However, the same syntax \uFFFF
is also used to insert Unicode characters into literal strings in the Java source code. Pattern.compile("\u00E0")
will match both the single-code-point and double-code-point encodings of à
, while Pattern.compile("\\u00E0")
matches only the single-code-point version. Remember that when writing a regex as a Java string literal, backslashes must be escaped. The former Java code compiles the regex à
, while the latter compiles \u00E0
. Depending on what you're doing, the difference may be significant."
回答2:
Are you talking about Unicode categories, like letters? These are matched by a regex of the form \p{CAT}
, where "CAT" is the category code like L
for any letter, or a subcategory like Lu
for uppercase or Lt
for title-case.
回答3:
Quoting from the JavaDoc of java.util.regex.Pattern.
Unicode support
This class is in conformance with Level 1 of Unicode Technical Standard #18: Unicode Regular Expression Guidelines, plus RL2.1 Canonical Equivalents.
Unicode escape sequences such as \u2014 in Java source code are processed as described in §3.3 of the Java Language Specification. Such escape sequences are also implemented directly by the regular-expression parser so that Unicode escapes can be used in expressions that are read from files or from the keyboard. Thus the strings "\u2014" and "\\u2014", while not equal, compile into the same pattern, which matches the character with hexadecimal value 0x2014.
Unicode blocks and categories are written with the \p and \P constructs as in Perl. \p{prop} matches if the input has the property prop, while \P{prop} does not match if the input has that property. Blocks are specified with the prefix In, as in InMongolian. Categories may be specified with the optional prefix Is: Both \p{L} and \p{IsL} denote the category of Unicode letters. Blocks and categories can be used both inside and outside of a character class.
The supported categories are those of The Unicode Standard in the version specified by the Character class. The category names are those defined in the Standard, both normative and informative. The block names supported by Pattern are the valid block names accepted and defined by UnicodeBlock.forName.
来源:https://stackoverflow.com/questions/5315330/matching-e-g-a-unicode-letter-with-java-regexps