java - Java正则表达式匹配越南字符

标签 java regex

我必须编写一个正则表达式来限制输入字段,该字段仅允许越南字符,英语字符和数字。我知道如何限制英语字符([a-zA-Z])和数字([0-9]),但不知道如何限制越南字符。

谁能给我一个Java正则表达式来匹配越南字符?

越南字符就像:ể,ứ(编辑:但是我不全都知道。否则,我可以使用[a-list-of-chars],或者可能有一个范围,例如[a-d]而不是[abcd])

最佳答案

越南字母

越南语字母和英语字母的交集(即两个字母之间的共同点)是英文减去fjwz的字母。

在越南语中,aeiouy被视为元音。

除此之外,越南语还使用其他几个带有变音符号的字符。下面列出了字符的大写字母(小写版本具有1字符到1字符的映射,与德语中的ß不同):

  • 辅音:
    Đ: LATIN CAPITAL LETTER D WITH STROKE
    
  • 元音:
    Ă: LATIN CAPITAL LETTER A WITH BREVE
    Â: LATIN CAPITAL LETTER A WITH CIRCUMFLEX
    Ê: LATIN CAPITAL LETTER E WITH CIRCUMFLE
    Ô: LATIN CAPITAL LETTER O WITH CIRCUMFLEX
    Ơ: LATIN CAPITAL LETTER O WITH HORN
    Ư: LATIN CAPITAL LETTER U WITH HORN
    

  • 越南语有6个音调,除了第一个音调外,其他5个音调由元音上的另一个变音符号指示。音调变音符号是急性á,严重à,钩形,波浪号ã下的点。由于有(6 + 6)个元音乘以5个音调带变音符号,加上6个元音在第一个音调上已经带有变音符,因此有66个带变音符的元音符号:

    这是所有(67)个带变音符号的辅音和元音的列表:
      Á À Ã Ả Ạ
    Ă Ắ Ằ Ẳ Ẵ Ặ
    Â Ấ Ầ Ẩ Ẫ Ậ
    Đ
      É È Ẻ Ẽ Ẹ
    Ê Ế Ề Ể Ễ Ệ 
      Í Ì Ỉ Ĩ Ị
    Ô Ố Ồ Ổ Ỗ Ộ
    Ơ Ớ Ờ Ở Ỡ Ợ
      Ó Ò Õ Ỏ Ọ
    Ư Ứ Ừ Ử Ữ Ự
      Ú Ù Ủ Ũ Ụ
      Ý Ỳ Ỷ Ỹ Ỵ
    

    这些字符分布在Unicode中的不同拉丁语块中。我从“字符映射表”中选择了这些字符,并且必须小心,不要选择与上述字符在视觉上相同的字符。可以肯定的是,我们可以打印字符的名称,并检查它们是拉丁字符,而不是希腊字母或西里尔字母。
    String VIETNAMESE_DIACRITIC_CHARACTERS = "ẮẰẲẴẶĂẤẦẨẪẬÂÁÀÃẢẠĐẾỀỂỄỆÊÉÈẺẼẸÍÌỈĨỊỐỒỔỖỘÔỚỜỞỠỢƠÓÒÕỎỌỨỪỬỮỰƯÚÙỦŨỤÝỲỶỸỴ";
    
    for (char c: VIETNAMESE_DIACRITIC_CHARACTERS.toCharArray()) {
        System.out.println(c + ": " + Character.getName(c));
    }
    

    组合字符

    越南语输入法(例如Unikey)有2种模式:单代码点模式(“Unicode d ngsẵn”)和组合标记模式(“Unicodetổhợp”)。

    例如,对于相同字符(U + 1EE3),可以有几种方法来指定它:
  • 作为单个代码点(1个代码点):
  • 作为ơ(U + 01A1)和下面的点(U + 0323)的组合(2个代码点):ợ
  • 作为o的组合,组合钩子(U + 031B)和下面的组合点(U + 0323)(3个代码点):ợ

  • 您可以将这些字符复制到浏览器的控制台中,并检查其长度:
    ["ợ","ợ","ợ"].forEach(function (e) {console.log(e.length);})
    

    如果要匹配上述所有3个变体,则必须列出所有可能的组合和排列以指定字符,您必须对上面列出的所有带有变音符号的字符(大写和大写)执行此操作小写。

    够容易吗?

    即使您回答“是”,您的代码也将成为无法理解的混乱局面。

    Canonical Equivalence

    由于有多种方法可以指定相同的文本,而无需进行任何转换,因此无法将ợ比较为相等。
    "ợ".equals("ợ") --> false
    

    因此,Unicode标准定义了将上述指定为规范等效的所有3种方式,并且还定义了用于标准化字符串以进行比较的方法。

    Java模式对规范等效性的支持
    Pattern类的参考实现(由Oracle,在Windows和其他平台上广泛使用)具有(部分)支持使用Pattern.CANON_EQ模式的规范对等匹配。从thisthis错误报告中可以看出,它具有极高的错误性,无法使用。在撰写本文时,由于CANON_EQ是“受支持的”,因此所有版本上都存在此错误,并且不可能在短期内得到修复。但是,它并没有被完全破坏,我们仍然可以使用该选件当前提供的任何功能。



    以下是用于匹配越南语+英语字母的Pattern的构造:
    String VIETNAMESE_DIACRITIC_CHARACTERS 
            = "ẮẰẲẴẶĂẤẦẨẪẬÂÁÀÃẢẠĐẾỀỂỄỆÊÉÈẺẼẸÍÌỈĨỊỐỒỔỖỘÔỚỜỞỠỢƠÓÒÕỎỌỨỪỬỮỰƯÚÙỦŨỤÝỲỶỸỴ";
    
    Pattern p =
        Pattern.compile("(?:[" + VIETNAMESE_DIACRITIC_CHARACTERS + "]|[A-Z])++",
                        Pattern.CANON_EQ |
                        Pattern.CASE_INSENSITIVE |
                        Pattern.UNICODE_CASE);
    

    附加标志Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE用于使模式对所有Unicode字符不区分大小写。仅Pattern.CASE_INSENSITIVE仅会使模式与US-ASCII字符集中的字符区分大小写,不区分大小写。

    请注意,VIETNAMESE_DIACRITIC_CHARACTERS中的字符顺序很重要。我不建议您更改字符的顺序,除非您理解其中的含义。

    在对输入执行匹配之前,应使用规范分解(NKD)或规范组合(NKC)规范化输入。 它可以确保组合标记按规范顺序排列。

    无论输入是使用规范组合还是规范分解进行预处理,结果都相同。运行附录中的代码应该为第二和第三个输出返回视觉上相同的结果:

    Bạn chính là tác giả của Wikipedia Mọi người đều có thể biên tập bài ngay lập tức chỉ cần nhớ vài quy tắc Có sẵn rất nhiều trang trợ giúp như tạo bài sửa bài hay tải ảnh Bạn cũng đừng ngại đặt câu hỏi Hiện chúng ta có bài viết và thành viên
    Bạn chính là tác giả của Wikipedia Mọi người đều có thể biên tập bài ngay lập tức chỉ cần nhớ vài quy tắc Có sẵn rất nhiều trang trợ giúp như tạo bài sửa bài hay tải ảnh Bạn cũng đừng ngại đặt câu hỏi Hiện chúng ta có bài viết và thành viên
    尝试失败

    这是一些失败的尝试,这些尝试将用于解释为什么正则表达式的构造如上所示。

    尝试1次
    String VIETNAMESE_DIACRITIC_CHARACTERS 
            = "ẮẰẲẴẶĂẤẦẨẪẬÂÁÀÃẢẠĐẾỀỂỄỆÊÉÈẺẼẸÍÌỈĨỊỐỒỔỖỘÔỚỜỞỠỢƠÓÒÕỎỌỨỪỬỮỰƯÚÙỦŨỤÝỲỶỸỴ";
    
    Pattern p =
        Pattern.compile("[A-Z" + VIETNAMESE_DIACRITIC_CHARACTERS + "]++",
                        Pattern.CANON_EQ |
                        Pattern.CASE_INSENSITIVE |
                        Pattern.UNICODE_CASE);
    

    为什么我们不将A-Z包含在单个字符类中,而不是将其放在单独的字符类中并与变音符号类交替出现?

    不,当我们尝试匹配输入字符串的规范分解时,结果将被破坏。变音符号根本不匹配。

    Ba n chi nh la ta c gia cu a Wikipedia Mo i ngu o i đe u co the bie n ta p ba i ngay la p tu c chi ca n nho va i quy ta c Co sa n ra t nhie u trang tro giu p nhu ta o ba i su a ba i hay ta i a nh Ba n cu ng đu ng nga i đa t ca u ho i Hie n chu ng ta co ba i vie t va tha nh vie n
    尝试2
    String VIETNAMESE_DIACRITIC_CHARACTERS 
            = "ÁÀÃẢẠĂẮẰẲẴẶÂẤẦẨẪẬĐÉÈẺẼẸÊẾỀỂỄỆÍÌỈĨỊÓÒÕỎỌÔỐỒỔỖỘƠỚỜỞỠỢÚÙỦŨỤƯỨỪỬỮỰÝỲỶỸỴ";
    
    Pattern p =
        Pattern.compile("(?:[" + VIETNAMESE_DIACRITIC_CHARACTERS + "]|[A-Z])++",
                        Pattern.CANON_EQ |
                        Pattern.CASE_INSENSITIVE |
                        Pattern.UNICODE_CASE);
    

    变音符号是在字符类中声明的,因此当我更改字符顺序时,代码应具有相同的行为...对吗?

    不,当我们尝试匹配输入字符串的规范分解时,某些结果会损坏。

    Bạn chính là tác giả của Wikipedia Mọi ngươ i đê u có thê biên tạ p bài ngay lạ p tư c chỉ câ n nhơ vài quy tă c Có să n râ t nhiê u trang trơ giúp như tạo bài sư a bài hay tải ảnh Bạn cũng đư ng ngại đạ t câu hỏi Hiẹ n chúng ta có bài viê t và thành viên
    说明

    参考实现(Oracle)通过选择表达式中的字符来实现Pattern.CANON_EQ模式,这些字符可以在规范分解下扩展为多个字符并执行正则表达式的文本转换。然后,将按照常规编译表达式。

    第一次转换正则表达式不能正确解析表达式,因此它表现出疯狂的行为以进行非常简单的匹配,如上面的错误报告所示。

    幸运的是,如果正则表达式中存在不匹配的Pattern,则(类在转换后会吐出该正则表达式。因此,我们只需在末尾添加(即可触发PatternSyntaxException并查看转换后的正则表达式字符串。

    让我们弄乱上面的解决方案正则表达式,看看进入编译步骤的正则表达式字符串是什么:
    java.util.regex.PatternSyntaxException: Unclosed group near index 596
    (?:(?:[Đ]|Ắ|Ắ|Ắ|Ằ|Ằ|Ằ|Ẳ|Ẳ|Ẳ|Ẵ|Ẵ|Ẵ|Ặ|Ặ|Ặ|Ặ|Ặ|Ặ|Ă|Ă|Ấ|Ấ|Ấ|Ầ|Ầ|Ầ|Ẩ|Ẩ|Ẩ|Ẫ|Ẫ|Ẫ|Ậ|Ậ|Ậ|Ậ|Ậ|Ậ|Â|Â|Á|Á|À|À|Ã|Ã|Ả|Ả|Ạ|Ạ|Ế|Ế|Ế|Ề|Ề|Ề|Ể|Ể|Ể|Ễ|Ễ|Ễ|Ệ|Ệ|Ệ|Ệ|Ệ|Ệ|Ê|Ê|É|É|È|È|Ẻ|Ẻ|Ẽ|Ẽ|Ẹ|Ẹ|Í|Í|Ì|Ì|Ỉ|Ỉ|Ĩ|Ĩ|Ị|Ị|Ố|Ố|Ố|Ồ|Ồ|Ồ|Ổ|Ổ|Ổ|Ỗ|Ỗ|Ỗ|Ộ|Ộ|Ộ|Ộ|Ộ|Ộ|Ô|Ô|Ớ|Ớ|Ớ|Ớ|Ớ|Ớ|Ờ|Ờ|Ờ|Ờ|Ờ|Ờ|Ở|Ở|Ở|Ở|Ở|Ở|Ỡ|Ỡ|Ỡ|Ỡ|Ỡ|Ỡ|Ợ|Ợ|Ợ|Ợ|Ợ|Ợ|Ơ|Ơ|Ó|Ó|Ò|Ò|Õ|Õ|Ỏ|Ỏ|Ọ|Ọ|Ứ|Ứ|Ứ|Ứ|Ứ|Ứ|Ừ|Ừ|Ừ|Ừ|Ừ|Ừ|Ử|Ử|Ử|Ử|Ử|Ử|Ữ|Ữ|Ữ|Ữ|Ữ|Ữ|Ự|Ự|Ự|Ự|Ự|Ự|Ư|Ư|Ú|Ú|Ù|Ù|Ủ|Ủ|Ũ|Ũ|Ụ|Ụ|Ý|Ý|Ỳ|Ỳ|Ỷ|Ỷ|Ỹ|Ỹ|Ỵ|Ỵ)|[A-Z])++(
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        ^
    

    如我们所见,引擎捕获了可以在“规范分解”下扩展的所有字符,将其移出字符类之外并建立了替代。

    仍然不太清楚相同字符交替交替发生的情况,因此我将在每个字符之间插入空格:

    ( ? : ( ? : [ Đ ] | A ̆ ́ | Ă ́ | Ắ | A ̆ ̀ | Ă ̀ | Ằ | A ̆ ̉ | Ă ̉ | Ẳ | A ̆ ̃ | Ă ̃ | Ẵ | A ̣ ̆ | Ạ ̆ | Ặ | A ̆ ̣ | Ă ̣ | Ặ | A ̆ | Ă | A ̂ ́ | Â ́ | Ấ | A ̂ ̀ | Â ̀ | Ầ | A ̂ ̉ | Â ̉ | Ẩ | A ̂ ̃ | Â ̃ | Ẫ | A ̣ ̂ | Ạ ̂ | Ậ | A ̂ ̣ | Â ̣ | Ậ | A ̂ | Â | A ́ | Á | A ̀ | À | A ̃ | Ã | A ̉ | Ả | A ̣ | Ạ | E ̂ ́ | Ê ́ | Ế | E ̂ ̀ | Ê ̀ | Ề | E ̂ ̉ | Ê ̉ | Ể | E ̂ ̃ | Ê ̃ | Ễ | E ̣ ̂ | Ẹ ̂ | Ệ | E ̂ ̣ | Ê ̣ | Ệ | E ̂ | Ê | E ́ | É | E ̀ | È | E ̉ | Ẻ | E ̃ | Ẽ | E ̣ | Ẹ | I ́ | Í | I ̀ | Ì | I ̉ | Ỉ | I ̃ | Ĩ | I ̣ | Ị | O ̂ ́ | Ô ́ | Ố | O ̂ ̀ | Ô ̀ | Ồ | O ̂ ̉ | Ô ̉ | Ổ | O ̂ ̃ | Ô ̃ | Ỗ | O ̣ ̂ | Ọ ̂ | Ộ | O ̂ ̣ | Ô ̣ | Ộ | O ̂ | Ô | O ̛ ́ | Ơ ́ | Ớ | O ́ ̛ | Ó ̛ | Ớ | O ̛ ̀ | Ơ ̀ | Ờ | O ̀ ̛ | Ò ̛ | Ờ | O ̛ ̉ | Ơ ̉ | Ở | O ̉ ̛ | Ỏ ̛ | Ở | O ̛ ̃ | Ơ ̃ | Ỡ | O ̃ ̛ | Õ ̛ | Ỡ | O ̛ ̣ | Ơ ̣ | Ợ | O ̣ ̛ | Ọ ̛ | Ợ | O ̛ | Ơ | O ́ | Ó | O ̀ | Ò | O ̃ | Õ | O ̉ | Ỏ | O ̣ | Ọ | U ̛ ́ | Ư ́ | Ứ | U ́ ̛ | Ú ̛ | Ứ | U ̛ ̀ | Ư ̀ | Ừ | U ̀ ̛ | Ù ̛ | Ừ | U ̛ ̉ | Ư ̉ | Ử | U ̉ ̛ | Ủ ̛ | Ử | U ̛ ̃ | Ư ̃ | Ữ | U ̃ ̛ | Ũ ̛ | Ữ | U ̛ ̣ | Ư ̣ | Ự | U ̣ ̛ | Ụ ̛ | Ự | U ̛ | Ư | U ́ | Ú | U ̀ | Ù | U ̉ | Ủ | U ̃ | Ũ | U ̣ | Ụ | Y ́ | Ý | Y ̀ | Ỳ | Y ̉ | Ỷ | Y ̃ | Ỹ | Y ̣ | Ỵ ) | [ A - Z ] ) + + (
    我们可以看到相同字符重复的串实际上不是相同的-它们是代表相同字符的不同序列。

    使用相同的方法,让我们在尝试2中分析该正则表达式以查看其失败的原因。
    java.util.regex.PatternSyntaxException: Unclosed group near index 596
    (?:(?:[Đ]|Á|Á|À|À|Ã|Ã|Ả|Ả|Ạ|Ạ|Ă|Ă|Ắ|Ắ|Ắ|Ằ|Ằ|Ằ|Ẳ|Ẳ|Ẳ|Ẵ|Ẵ|Ẵ|Ặ|Ặ|Ặ|Ặ|Ặ|Ặ|Â|Â|Ấ|Ấ|Ấ|Ầ|Ầ|Ầ|Ẩ|Ẩ|Ẩ|Ẫ|Ẫ|Ẫ|Ậ|Ậ|Ậ|Ậ|Ậ|Ậ|É|É|È|È|Ẻ|Ẻ|Ẽ|Ẽ|Ẹ|Ẹ|Ê|Ê|Ế|Ế|Ế|Ề|Ề|Ề|Ể|Ể|Ể|Ễ|Ễ|Ễ|Ệ|Ệ|Ệ|Ệ|Ệ|Ệ|Í|Í|Ì|Ì|Ỉ|Ỉ|Ĩ|Ĩ|Ị|Ị|Ó|Ó|Ò|Ò|Õ|Õ|Ỏ|Ỏ|Ọ|Ọ|Ô|Ô|Ố|Ố|Ố|Ồ|Ồ|Ồ|Ổ|Ổ|Ổ|Ỗ|Ỗ|Ỗ|Ộ|Ộ|Ộ|Ộ|Ộ|Ộ|Ơ|Ơ|Ớ|Ớ|Ớ|Ớ|Ớ|Ớ|Ờ|Ờ|Ờ|Ờ|Ờ|Ờ|Ở|Ở|Ở|Ở|Ở|Ở|Ỡ|Ỡ|Ỡ|Ỡ|Ỡ|Ỡ|Ợ|Ợ|Ợ|Ợ|Ợ|Ợ|Ú|Ú|Ù|Ù|Ủ|Ủ|Ũ|Ũ|Ụ|Ụ|Ư|Ư|Ứ|Ứ|Ứ|Ứ|Ứ|Ứ|Ừ|Ừ|Ừ|Ừ|Ừ|Ừ|Ử|Ử|Ử|Ử|Ử|Ử|Ữ|Ữ|Ữ|Ữ|Ữ|Ữ|Ự|Ự|Ự|Ự|Ự|Ự|Ý|Ý|Ỳ|Ỳ|Ỷ|Ỷ|Ỹ|Ỹ|Ỵ|Ỵ)|[A-Z])++(
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        ^
    

    在每个字符之间插入空格:

    ( ? : ( ? : [ Đ ] | A ́ | Á | A ̀ | À | A ̃ | Ã | A ̉ | Ả | A ̣ | Ạ | A ̆ | Ă | A ̆ ́ | Ă ́ | Ắ | A ̆ ̀ | Ă ̀ | Ằ | A ̆ ̉ | Ă ̉ | Ẳ | A ̆ ̃ | Ă ̃ | Ẵ | A ̣ ̆ | Ạ ̆ | Ặ | A ̆ ̣ | Ă ̣ | Ặ | A ̂ | Â | A ̂ ́ | Â ́ | Ấ | A ̂ ̀ | Â ̀ | Ầ | A ̂ ̉ | Â ̉ | Ẩ | A ̂ ̃ | Â ̃ | Ẫ | A ̣ ̂ | Ạ ̂ | Ậ | A ̂ ̣ | Â ̣ | Ậ | E ́ | É | E ̀ | È | E ̉ | Ẻ | E ̃ | Ẽ | E ̣ | Ẹ | E ̂ | Ê | E ̂ ́ | Ê ́ | Ế | E ̂ ̀ | Ê ̀ | Ề | E ̂ ̉ | Ê ̉ | Ể | E ̂ ̃ | Ê ̃ | Ễ | E ̣ ̂ | Ẹ ̂ | Ệ | E ̂ ̣ | Ê ̣ | Ệ | I ́ | Í | I ̀ | Ì | I ̉ | Ỉ | I ̃ | Ĩ | I ̣ | Ị | O ́ | Ó | O ̀ | Ò | O ̃ | Õ | O ̉ | Ỏ | O ̣ | Ọ | O ̂ | Ô | O ̂ ́ | Ô ́ | Ố | O ̂ ̀ | Ô ̀ | Ồ | O ̂ ̉ | Ô ̉ | Ổ | O ̂ ̃ | Ô ̃ | Ỗ | O ̣ ̂ | Ọ ̂ | Ộ | O ̂ ̣ | Ô ̣ | Ộ | O ̛ | Ơ | O ̛ ́ | Ơ ́ | Ớ | O ́ ̛ | Ó ̛ | Ớ | O ̛ ̀ | Ơ ̀ | Ờ | O ̀ ̛ | Ò ̛ | Ờ | O ̛ ̉ | Ơ ̉ | Ở | O ̉ ̛ | Ỏ ̛ | Ở | O ̛ ̃ | Ơ ̃ | Ỡ | O ̃ ̛ | Õ ̛ | Ỡ | O ̛ ̣ | Ơ ̣ | Ợ | O ̣ ̛ | Ọ ̛ | Ợ | U ́ | Ú | U ̀ | Ù | U ̉ | Ủ | U ̃ | Ũ | U ̣ | Ụ | U ̛ | Ư | U ̛ ́ | Ư ́ | Ứ | U ́ ̛ | Ú ̛ | Ứ | U ̛ ̀ | Ư ̀ | Ừ | U ̀ ̛ | Ù ̛ | Ừ | U ̛ ̉ | Ư ̉ | Ử | U ̉ ̛ | Ủ ̛ | Ử | U ̛ ̃ | Ư ̃ | Ữ | U ̃ ̛ | Ũ ̛ | Ữ | U ̛ ̣ | Ư ̣ | Ự | U ̣ ̛ | Ụ ̛ | Ự | Y ́ | Ý | Y ̀ | Ỳ | Y ̉ | Ỷ | Y ̃ | Ỹ | Y ̣ | Ỵ ) | [ A - Z ] ) + + (
    注意,在正则表达式中A ̂ | ÂA ̂ ̀ | Â ̀ | Ầ之前。这意味着A ̂将首先在输入的Ầ(A ̂ ̀)上尝试,并且在下一次迭代中不匹配任何内容时,重复将结束。

    通常,由于交替顺序很重要,因此在2个字符串之间(其中一个字符串是另一字符串的前缀),较长的字符串应优先出现在交替中。在我们的情况下,我们需要将具有更多变音符号的字符放在具有较少或没有变音符号的字符之前。

    尝试1的相同问题:
    java.util.regex.PatternSyntaxException: Unclosed group near index 589
    (?:[A-ZĐ]|Ắ|Ắ|Ắ|Ằ|Ằ|Ằ|Ẳ|Ẳ|Ẳ|Ẵ|Ẵ|Ẵ|Ặ|Ặ|Ặ|Ặ|Ặ|Ặ|Ă|Ă|Ấ|Ấ|Ấ|Ầ|Ầ|Ầ|Ẩ|Ẩ|Ẩ|Ẫ|Ẫ|Ẫ|Ậ|Ậ|Ậ|Ậ|Ậ|Ậ|Â|Â|Á|Á|À|À|Ã|Ã|Ả|Ả|Ạ|Ạ|Ế|Ế|Ế|Ề|Ề|Ề|Ể|Ể|Ể|Ễ|Ễ|Ễ|Ệ|Ệ|Ệ|Ệ|Ệ|Ệ|Ê|Ê|É|É|È|È|Ẻ|Ẻ|Ẽ|Ẽ|Ẹ|Ẹ|Í|Í|Ì|Ì|Ỉ|Ỉ|Ĩ|Ĩ|Ị|Ị|Ố|Ố|Ố|Ồ|Ồ|Ồ|Ổ|Ổ|Ổ|Ỗ|Ỗ|Ỗ|Ộ|Ộ|Ộ|Ộ|Ộ|Ộ|Ô|Ô|Ớ|Ớ|Ớ|Ớ|Ớ|Ớ|Ờ|Ờ|Ờ|Ờ|Ờ|Ờ|Ở|Ở|Ở|Ở|Ở|Ở|Ỡ|Ỡ|Ỡ|Ỡ|Ỡ|Ỡ|Ợ|Ợ|Ợ|Ợ|Ợ|Ợ|Ơ|Ơ|Ó|Ó|Ò|Ò|Õ|Õ|Ỏ|Ỏ|Ọ|Ọ|Ứ|Ứ|Ứ|Ứ|Ứ|Ứ|Ừ|Ừ|Ừ|Ừ|Ừ|Ừ|Ử|Ử|Ử|Ử|Ử|Ử|Ữ|Ữ|Ữ|Ữ|Ữ|Ữ|Ự|Ự|Ự|Ự|Ự|Ự|Ư|Ư|Ú|Ú|Ù|Ù|Ủ|Ủ|Ũ|Ũ|Ụ|Ụ|Ý|Ý|Ỳ|Ỳ|Ỷ|Ỷ|Ỹ|Ỹ|Ỵ|Ỵ)++(
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 ^
    

    由于交替是在原始字符类之后形成的,因此将首先尝试[A-Z]中的元音,从而导致重复在遇到杂散组合标记时尽早终止。

    参考
  • Vietnamese Alphabetical System
  • Common Vietnamese Input Method
  • Optimized Unicode Composition and Decomposition

  • 附录

    以下是测试程序的源代码。

    Demo on ideone
    import java.util.regex.*;
    import java.text.*;
    
    class Ideone
    {
        public static void main (String[] args) throws java.lang.Exception
        {
            String VIETNAMESE_DIACRITIC_CHARACTERS 
                = "ẮẰẲẴẶĂẤẦẨẪẬÂÁÀÃẢẠĐẾỀỂỄỆÊÉÈẺẼẸÍÌỈĨỊỐỒỔỖỘÔỚỜỞỠỢƠÓÒÕỎỌỨỪỬỮỰƯÚÙỦŨỤÝỲỶỸỴ";
            /*
            for (char c: VIETNAMESE_DIACRITIC_CHARACTERS.toCharArray()) {
                System.out.println(c + ": " + Character.getName(c));
            }
            */
    
            String tests[] = new String[3];
            tests[0] = 
                "Bạn chính là tác giả của Wikipedia!\n" + 
                "Mọi người đều có thể biên tập bài ngay lập tức, chỉ cần nhớ vài quy tắc." +
                "Có sẵn rất nhiều trang trợ giúp như tạo bài, sửa bài hay tải ảnh." + 
                "Bạn cũng đừng ngại đặt câu hỏi.\n" +
                "Hiện chúng ta có 1.109.446 bài viết và 406.782 thành viên.";
    
            tests[1] =
                Normalizer.normalize(tests[0], Normalizer.Form.NFD);
            /*
            for (char c: tests[1].toCharArray()) {
                System.out.printf("%04x ", (int) c);
            }
            */  
            tests[2] =
                Normalizer.normalize(tests[0], Normalizer.Form.NFC);
    
            try {
                Pattern p = Pattern.compile("(?:[" + VIETNAMESE_DIACRITIC_CHARACTERS + "]|[A-Z])++", Pattern.CANON_EQ | Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
    
                for (String t: tests) {
                    Matcher m = p.matcher(t);
                    while (m.find()) {
                        System.out.print(m.group() + " ");
                    }
                    System.out.println();
                }
            } catch (Exception e) {
                System.out.println(e);
            }
        }
    }
    

    关于java - Java正则表达式匹配越南字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26543329/

    相关文章:

    regex - 如何在 Perl 正则表达式中捕捉一个点?

    regex - 用于提取多行 block 的 perl 正则表达式

    java - 我的 Java 正则表达式从不匹配,尽管它总是通过在线 java 正则表达式检查器

    java - Byte Buddy 和 ClassLoadingStrategy.UsingLookup

    java - 返回假;声明没有 "return"

    java - NativeActivity 不显示在屏幕上

    javascript - jQuery 在字符串中查找 url 并用 href 换行(如果尚未换行)

    html - 从格式错误的 pdf 表中抓取数据

    Java Dispatching-Runtime类型

    java - 在java中检索MySQL时间