What you are looking for are Unicode properties.

e.g. \p{L} is any kind of letter from any language

So a regex to match such a Chinese word could be something like

\p{L}+

There are many such properties, for more details see regular-expressions.info

Another option is to use the modifier

Pattern.UNICODE_CHARACTER_CLASS

In Java 7 there is a new property Pattern.UNICODE_CHARACTER_CLASS that enables the Unicode version of the predefined character classes see my answer here for some more details and links

You could do something like this

Pattern p = Pattern.compile("\\w+", Pattern.UNICODE_CHARACTER_CLASS);

and \w would match all letters and all digits from any languages (and of course some word combining characters like _).

Answer from stema on Stack Overflow
Top answer
1 of 5
145

What you are looking for are Unicode properties.

e.g. \p{L} is any kind of letter from any language

So a regex to match such a Chinese word could be something like

\p{L}+

There are many such properties, for more details see regular-expressions.info

Another option is to use the modifier

Pattern.UNICODE_CHARACTER_CLASS

In Java 7 there is a new property Pattern.UNICODE_CHARACTER_CLASS that enables the Unicode version of the predefined character classes see my answer here for some more details and links

You could do something like this

Pattern p = Pattern.compile("\\w+", Pattern.UNICODE_CHARACTER_CLASS);

and \w would match all letters and all digits from any languages (and of course some word combining characters like _).

2 of 5
16

To address NLS support and avoid accepting English special character, we can use below pattern...

[a-zA-Z0-9 \u0080-\u9fff]*+

For UTF code point reference: http://www.utf8-chartable.de/unicode-utf8-table.pl

Code snippet:

    String vowels = "అఆఇఈఉఊఋఌఎఏఐఒఓఔౠౡ";
    String consonants = "కఖగఘఙచఛజఝఞటఠడఢణతథదధనపఫబభమయరఱలళవశషసహ";
    String signsAndPunctuations = "కఁకంకఃకాకికీకుకూకృకౄకెకేకైకొకోకౌక్కౕకౖ";
    String symbolsAndNumerals = "౦౧౨౩౪౫౬౭౮౯";
    String engChinesStr = "ABC導字會";


    Pattern ALPHANUMERIC_AND_SPACE_PATTERN_TELUGU = Pattern
            .compile("[a-zA-Z0-9 \\u0c00-\\u0c7f]*+");
    System.out.println(ALPHANUMERIC_AND_SPACE_PATTERN_TELUGU.matcher(vowels)
            .matches());


    Pattern ALPHANUMERIC_AND_SPACE_PATTERN_CHINESE = Pattern
            .compile("[a-zA-Z0-9 \\u4e00-\\u9fff]*+");

    Pattern ENGLISH_ALPHANUMERIC_SPACE_AND_NLS_PATTERN = Pattern
            .compile("[a-zA-Z0-9 \\u0080-\\u9fff]*+");

    System.out.println(ENGLISH_ALPHANUMERIC_SPACE_AND_NLS_PATTERN.matcher(engChinesStr)
            .matches());
🌐
Oracle
docs.oracle.com › javase › tutorial › essential › regex › unicode.html
Unicode Support (The Java™ Tutorials > Essential Java Classes > Regular Expressions)
See Java Language Changes for a ... or deprecated options for all JDK releases. As of the JDK 7 release, Regular Expression pattern matching has expanded functionality to support Unicode 6.0....
Discussions

Java Regex for Unicode or special character - Stack Overflow
@CasimiretHippolyte "UNICODE_CASE ... that is, it enables Unicode-aware case folding" ... Save this answer. ... Show activity on this post. I'm guessing that maybe this expression might work, based on the one you have provided: import java.util.regex.Matcher; import ... More on stackoverflow.com
🌐 stackoverflow.com
Java regex unicode support? - Stack Overflow
I'm working on an app that receives feedback from customers via email about a particular product. Currently I'm using java matcher and pattern classes to use regex's to parse certain snippets and More on stackoverflow.com
🌐 stackoverflow.com
regex - Matching (e.g.) a Unicode letter with Java regexps - Stack Overflow
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 ... More on stackoverflow.com
🌐 stackoverflow.com
regex - Unicode equivalents for \w and \b in Java regular expressions? - Stack Overflow
Many modern regex implementations interpret the \w character class shorthand as "any letter, digit, or connecting punctuation" (usually: underscore). That way, a regex like \w+ matches words like h... More on stackoverflow.com
🌐 stackoverflow.com
🌐
O'Reilly
oreilly.com › library › view › java-9-regular › 9781787288706 › 22b9373d-8662-4c03-94d5-90cbb7cc15b7.xhtml
Examples of matching Unicode text in regular expressions - Java 9 Regular Expressions [Book]
July 25, 2017 - Examples of matching Unicode text in regular expressions The following regex will match accented characters, such as "à": ^\p{L}+$ The following regex will match a text consisting... - Selection from Java 9 Regular Expressions [Book]
Author   Anubhava Srivastava
Published   2017
Pages   158
🌐
Unicode
unicode.org › reports › tr18
UTS #18: Unicode Regular Expressions
However, the names used by the implementation for these properties may differ from the formal Unicode names for the properties. For example, if a regex engine already has a property called "Alphabetic", for backwards compatibility it may need to use a distinct name, such as "Unicode_Alphabetic", for the corresponding property listed in RL1.2.
🌐
TutorialsPoint
tutorialspoint.com › javaregex › javaregex_unicode_character_classes.htm
Matching Unicode Character Classes
Following are various examples of matching Unicode character classes using regular expression in java.
🌐
javathinking
javathinking.com › blog › java-regex-for-support-unicode
Java Regex for Unicode Support: How to Match UTF-8 Characters (Including Chinese Examples) — javathinking.com
This blog will guide you through Java’s regex capabilities for Unicode, with a focus on practical examples involving Chinese characters (a common use case for Unicode support). By the end, you’ll be able to confidently match, validate, and manipulate UTF-8 text in Java using regex.
🌐
Saxon diaries
blog.saxonica.com › mike › 2010 › 01 › unicode-regular-expressions-and-java.html
Unicode, regular expressions, and Java
January 13, 2010 - It's a little hard to unearth the history now of which specifications mandated which Unicode version, but the current situation seems to be that JDK 1.5 and 1.6 support Unicode 4.0, while the schema (and hence XPath) specs originally specified ...
Find elsewhere
🌐
Oracle
docs.oracle.com › javase › 8 › docs › api › java › util › regex › Pattern.html
Pattern (Java Platform SE 8 )
1 week ago - The following Predefined Character classes and POSIX character classes are in conformance with the recommendation of Annex C: Compatibility Properties of Unicode Regular Expression , when UNICODE_CHARACTER_CLASS flag is specified. Categories that behave like the java.lang.Character boolean ismethodname methods (except for the deprecated ones) are available through the same \p{prop} syntax where the specified property has the name javamethodname.
🌐
Coderanch
coderanch.com › t › 565539 › java › Regular-expression-unicode
Regular expression help with unicode (Java in General forum at Coderanch)
January 25, 2012 - Hi, I'm looking for regular expression where String consists of a mixture of unicode letters and numerical digits only, with at least one of each. The closest I got to is Java String: "^[\\p{L}\\p{N}]+$" The problem is, this still allows if the string is entirely numbers or entirely letters, so strings like "1234567" or "abcdef" still match. Does anyone know how to fix this? Thanks, Sri ... This seems to work. There's probably a cleaner way with a single regex, and, honestly, it would be clearer just to use 2 different regexes--one that says "contains at least one letter" and one that says "contains at least one digit", and then test that it matches regex1 AND matches regex2.
Top answer
1 of 3
250

Source code

The source code for the rewriting functions I discuss below is available here.

Update in Java 7

Sun’s updated Pattern class for JDK7 has a marvelous new flag, UNICODE_CHARACTER_CLASS, which makes everything work right again. It’s available as an embeddable (?U) for inside the pattern, so you can use it with the String class’s wrappers, too. It also sports corrected definitions for various other properties, too. It now tracks The Unicode Standard, in both RL1.2 and RL1.2a from UTS#18: Unicode Regular Expressions. This is an exciting and dramatic improvement, and the development team is to be commended for this important effort.


Java’s Regex Unicode Problems

The problem with Java regexes is that the Perl 1.0 charclass escapes — meaning \w, \b, \s, \d and their complements — are not in Java extended to work with Unicode. Alone amongst these, \b enjoys certain extended semantics, but these map neither to \w, nor to Unicode identifiers, nor to Unicode line-break properties.

Additionally, the POSIX properties in Java are accessed this way:

POSIX syntax    Java syntax

[[:Lower:]]     \p{Lower}
[[:Upper:]]     \p{Upper}
[[:ASCII:]]     \p{ASCII}
[[:Alpha:]]     \p{Alpha}
[[:Digit:]]     \p{Digit}
[[:Alnum:]]     \p{Alnum}
[[:Punct:]]     \p{Punct}
[[:Graph:]]     \p{Graph}
[[:Print:]]     \p{Print}
[[:Blank:]]     \p{Blank}
[[:Cntrl:]]     \p{Cntrl}
[[:XDigit:]]    \p{XDigit}
[[:Space:]]     \p{Space}

This is a real mess, because it means that things like Alpha, Lower, and Space do not in Java map to the Unicode Alphabetic, Lowercase, or Whitespace properties. This is exceeedingly annoying. Java’s Unicode property support is strictly antemillennial, by which I mean it supports no Unicode property that has come out in the last decade.

Not being able to talk about whitespace properly is super-annoying. Consider the following table. For each of those code points, there is both a J-results column for Java and a P-results column for Perl or any other PCRE-based regex engine:

             Regex    001A    0085    00A0    2029
                      J  P    J  P    J  P    J  P
                \s    1  1    0  1    0  1    0  1
               \pZ    0  0    0  0    1  1    1  1
            \p{Zs}    0  0    0  0    1  1    0  0
         \p{Space}    1  1    0  1    0  1    0  1
         \p{Blank}    0  0    0  0    0  1    0  0
    \p{Whitespace}    -  1    -  1    -  1    -  1
\p{javaWhitespace}    1  -    0  -    0  -    1  -
 \p{javaSpaceChar}    0  -    0  -    1  -    1  -

See that?

Virtually every one of those Java white space results is   ̲w̲r̲o̲n̲g̲  according to Unicode. It’s a really big problem. Java is just messed up, giving answers that are “wrong” according to existing practice and also according to Unicode. Plus Java doesn’t even give you access to the real Unicode properties! In fact, Java does not support any property that corresponds to Unicode whitespace.


The Solution to All Those Problems, and More

To deal with this and many other related problems, yesterday I wrote a Java function to rewrite a pattern string that rewrites these 14 charclass escapes:

\w \W \s \S \v \V \h \H \d \D \b \B \X \R

by replacing them with things that actually work to match Unicode in a predictable and consistent fashion. It’s only an alpha prototype from a single hack session, but it is completely functional.

The short story is that my code rewrites those 14 as follows:

\s => [\u0009-\u000D\u0020\u0085\u00A0\u1680\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]
\S => [^\u0009-\u000D\u0020\u0085\u00A0\u1680\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]

\v => [\u000A-\u000D\u0085\u2028\u2029]
\V => [^\u000A-\u000D\u0085\u2028\u2029]

\h => [\u0009\u0020\u00A0\u1680\u180E\u2000-\u200A\u202F\u205F\u3000]
\H => [^\u0009\u0020\u00A0\u1680\u180E\u2000\u2001-\u200A\u202F\u205F\u3000]

\w => [\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]]
\W => [^\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]]

\b => (?:(?<=[\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]])(?![\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]])|(?<![\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]])(?=[\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]]))
\B => (?:(?<=[\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]])(?=[\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]])|(?<![\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]])(?![\pL\pM\p{Nd}\p{Nl}\p{Pc}[\p{InEnclosedAlphanumerics}&&\p{So}]]))

\d => \p{Nd}
\D => \P{Nd}

\R => (?:(?>\u000D\u000A)|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029])

\X => (?>\PM\pM*)

Some things to consider...

  • That uses for its \X definition what Unicode now refers to as a legacy grapheme cluster, not an extended grapheme cluster, as the latter is rather more complicated. Perl itself now uses the fancier version, but the old version is still perfectly workable for the most common situations. EDIT: See addendum at bottom.

  • What to do about \d depends on your intent, but the default is the Uniode definition. I can see people not always wanting \p{Nd}, but sometimes either [0-9] or \pN.

  • The two boundary definitions, \b and \B, are specifically written to use the \w definition.

  • That \w definition is overly broad, because it grabs the parenned letters not just the circled ones. The Unicode Other_Alphabetic property isn’t available until JDK7, so that’s the best you can do.


Exploring Boundaries

Boundaries have been a problem ever since Larry Wall first coined the \b and \B syntax for talking about them for Perl 1.0 back in 1987. The key to understanding how \b and \B both work is to dispel two pervasive myths about them:

  1. They are only ever looking for \w word characters, never for non-word characters.
  2. They do not specifically look for the edge of the string.

A \b boundary means:

    IF does follow word
        THEN doesn't precede word
    ELSIF doesn't follow word
        THEN does precede word

And those are all defined perfectly straightforwardly as:

  • follows word is (?<=\w).
  • precedes word is (?=\w).
  • doesn’t follow word is (?<!\w).
  • doesn’t precede word is (?!\w).

Therefore, since IF-THEN is encoded as an and ed-together AB in regexes, an or is X|Y, and because the and is higher in precedence than or, that is simply AB|CD. So every \b that means a boundary can be safely replaced with:

    (?:(?<=\w)(?!\w)|(?<!\w)(?=\w))

with the \w defined in the appropriate way.

(You might think it strange that the A and C components are opposites. In a perfect world, you should be able to write that AB|D, but for a while I was chasing down mutual exclusion contradictions in Unicode properties — which I think I’ve taken care of, but I left the double condition in the boundary just in case. Plus this makes it more extensible if you get extra ideas later.)

For the \B non-boundaries, the logic is:

    IF does follow word
        THEN does precede word
    ELSIF doesn't follow word
        THEN doesn't precede word

Allowing all instances of \B to be replaced with:

    (?:(?<=\w)(?=\w)|(?<!\w)(?!\w))

This really is how \b and \B behave. Equivalent patterns for them are

  • \b using the ((IF)THEN|ELSE) construct is (?(?<=\w)(?!\w)|(?=\w))
  • \B using the ((IF)THEN|ELSE) construct is (?(?=\w)(?<=\w)|(?<!\w))

But the versions with just AB|CD are fine, especially if you lack conditional patterns in your regex language — like Java. ☹

I’ve already verified the behaviour of the boundaries using all three equivalent definitions with a test suite that checks 110,385,408 matches per run, and which I've run on a dozen different data configurations according to:

     0 ..     7F    the ASCII range
    80 ..     FF    the non-ASCII Latin1 range
   100 ..   FFFF    the non-Latin1 BMP (Basic Multilingual Plane) range
 10000 .. 10FFFF    the non-BMP portion of Unicode (the "astral" planes)

However, people often want a different sort of boundary. They want something that is whitespace and edge-of-string aware:

  • left edge as (?:(?<=^)|(?<=\s))
  • right edge as (?=$|\s)

Fixing Java with Java

The code I posted in my other answer provides this and quite a few other conveniences. This includes definitions for natural-language words, dashes, hyphens, and apostrophes, plus a bit more.

It also allows you to specify Unicode characters in logical code points, not in idiotic UTF-16 surrogates. It’s hard to overstress how important that is! And that’s just for the string expansion.

For regex charclass substitution that makes the charclass in your Java regexes finally work on Unicode, and work correctly, grab the full source from here. You may do with it as you please, of course. If you make fixes to it, I’d love to hear of it, but you don’t have to. It’s pretty short. The guts of the main regex rewriting function is simple:

switch (code_point) {

    case 'b':  newstr.append(boundary);
               break; /* switch */
    case 'B':  newstr.append(not_boundary);
               break; /* switch */

    case 'd':  newstr.append(digits_charclass);
               break; /* switch */
    case 'D':  newstr.append(not_digits_charclass);
               break; /* switch */

    case 'h':  newstr.append(horizontal_whitespace_charclass);
               break; /* switch */
    case 'H':  newstr.append(not_horizontal_whitespace_charclass);
               break; /* switch */

    case 'v':  newstr.append(vertical_whitespace_charclass);
               break; /* switch */
    case 'V':  newstr.append(not_vertical_whitespace_charclass);
               break; /* switch */

    case 'R':  newstr.append(linebreak);
               break; /* switch */

    case 's':  newstr.append(whitespace_charclass);
               break; /* switch */
    case 'S':  newstr.append(not_whitespace_charclass);
               break; /* switch */

    case 'w':  newstr.append(identifier_charclass);
               break; /* switch */
    case 'W':  newstr.append(not_identifier_charclass);
               break; /* switch */

    case 'X':  newstr.append(legacy_grapheme_cluster);
               break; /* switch */

    default:   newstr.append('\\');
               newstr.append(Character.toChars(code_point));
               break; /* switch */

}
saw_backslash = false;

Anyway, that code is just an alpha release, stuff I hacked up over the weekend. It won’t stay that way.

For the beta I intend to:

  • fold together the code duplication

  • provide a clearer interface regarding unescaping string escapes versus augmenting regex escapes

  • provide some flexibility in the \d expansion, and maybe the \b

  • provide convenience methods that handle turning around and calling Pattern.compile or String.matches or whatnot for you

For production release, it should have javadoc and a JUnit test suite. I may include my gigatester, but it’s not written as JUnit tests.


Addendum

I have good news and bad news.

The good news is that I’ve now got a very close approximation to an extended grapheme cluster to use for an improved \X.

The bad news ☺ is that that pattern is:

(?:(?:\u000D\u000A)|(?:[\u0E40\u0E41\u0E42\u0E43\u0E44\u0EC0\u0EC1\u0EC2\u0EC3\u0EC4\uAAB5\uAAB6\uAAB9\uAABB\uAABC]*(?:[\u1100-\u115F\uA960-\uA97C]+|([\u1100-\u115F\uA960-\uA97C]*((?:[[\u1160-\u11A2\uD7B0-\uD7C6][\uAC00\uAC1C\uAC38]][\u1160-\u11A2\uD7B0-\uD7C6]*|[\uAC01\uAC02\uAC03\uAC04])[\u11A8-\u11F9\uD7CB-\uD7FB]*))|[\u11A8-\u11F9\uD7CB-\uD7FB]+|[^[\p{Zl}\p{Zp}\p{Cc}\p{Cf}&&[^\u000D\u000A\u200C\u200D]]\u000D\u000A])[[\p{Mn}\p{Me}\u200C\u200D\u0488\u0489\u20DD\u20DE\u20DF\u20E0\u20E2\u20E3\u20E4\uA670\uA671\uA672\uFF9E\uFF9F][\p{Mc}\u0E30\u0E32\u0E33\u0E45\u0EB0\u0EB2\u0EB3]]*)|(?s:.))

which in Java you’d write as:

String extended_grapheme_cluster = "(?:(?:\\u000D\\u000A)|(?:[\\u0E40\\u0E41\\u0E42\\u0E43\\u0E44\\u0EC0\\u0EC1\\u0EC2\\u0EC3\\u0EC4\\uAAB5\\uAAB6\\uAAB9\\uAABB\\uAABC]*(?:[\\u1100-\\u115F\\uA960-\\uA97C]+|([\\u1100-\\u115F\\uA960-\\uA97C]*((?:[[\\u1160-\\u11A2\\uD7B0-\\uD7C6][\\uAC00\\uAC1C\\uAC38]][\\u1160-\\u11A2\\uD7B0-\\uD7C6]*|[\\uAC01\\uAC02\\uAC03\\uAC04])[\\u11A8-\\u11F9\\uD7CB-\\uD7FB]*))|[\\u11A8-\\u11F9\\uD7CB-\\uD7FB]+|[^[\\p{Zl}\\p{Zp}\\p{Cc}\\p{Cf}&&[^\\u000D\\u000A\\u200C\\u200D]]\\u000D\\u000A])[[\\p{Mn}\\p{Me}\\u200C\\u200D\\u0488\\u0489\\u20DD\\u20DE\\u20DF\\u20E0\\u20E2\\u20E3\\u20E4\\uA670\\uA671\\uA672\\uFF9E\\uFF9F][\\p{Mc}\\u0E30\\u0E32\\u0E33\\u0E45\\u0EB0\\u0EB2\\u0EB3]]*)|(?s:.))";

¡Tschüß!

2 of 3
16

It's really unfortunate that \w doesn't work. The proposed solution \p{Alpha} doesn't work for me either.

It seems [\p{L}] catches all Unicode letters. So the Unicode equivalent of \w should be [\p{L}\p{Digit}_].

🌐
TutorialsPoint
tutorialspoint.com › javaregex › javaregex_unicode_class_latin.htm
Unicode Character Class \p{IsLatin}
The following example shows the usage of Unicode character class matching. package com.tutorialspoint; import java.util.regex.Matcher; import java.util.regex.Pattern; public class UnicodeCharacterClassDemo { private static final String REGEX = "\\p{IsLatin}"; private static final String INPUT = "Bb12 \tc!"; public static void main(String[] args) { // create a pattern Pattern pattern = Pattern.compile(REGEX); // get a matcher object Matcher matcher = pattern.matcher(INPUT); while(matcher.find()) { //Prints the start index of the match.
🌐
Regular-Expressions.info
regular-expressions.info › unicode.html
Regex Tutorial: Introduction to Unicode Regular Expressions
This change would affect you, for example, if your app was previously running on Java 11 or prior (based on Unicode 10.0.0 or prior) and is then migrated to Java 12 or later (based on Unicode 11.0.0 or later). Whether this actually impacts your application depends on whether you have any users in Georgia and whether your app uses regexes with \p{Ll} and/or \p{Lo}.
🌐
Java
download.java.net › java › early_access › valhalla › docs › api › java.base › java › util › regex › Pattern.html
Pattern (Java SE 23 & JDK 23 [build 1])
Unicode escape sequences such as \u2014 in Java source code are processed as described in section 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 ...
🌐
Icu-project
icu-project.org › docs › papers › iuc26_regexp.pdf pdf
Analyzing Unicode Text with Regular Expressions
Text Boundary Analysis in Java · Unicode and IBM Websphere (doc) (ppt) ICU design documents are checked into the Subversion repository. http://source.icu-project.org/repos/icu/icuhtml/trunk/design/ (for access with a web browser) Unicode Overview · Forms of Unicode: UTF-8, UTF-16, UTF-32 ·
🌐
Oracle
docs.oracle.com › javase › 7 › docs › api › java › util › regex › Pattern.html
Pattern (Java Platform SE 7 )
Unicode escape sequences such as \u2014 in Java source code are processed as described in section 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 ...