正则表达式匹配埃及象形文字

时间:2015-03-06 09:59:21

标签: regex unicode internationalization

我想知道匹配埃及象形文字的正则表达式。我完全无能为力,需要你的帮助。

我不能发信,因为堆栈溢出似乎无法识别它。

所以任何人都可以告诉我这些角色的unicode范围。

2 个答案:

答案 0 :(得分:38)

TLDNR:\p{Egyptian_Hieroglyphs}

的Javascript

Egyptian_Hieroglyphs属于“星体”平面,它使用超过16位来编码字符。从ES5开始,Javascript不支持星体平面(more on that),因此您必须使用代理对。第一个代理是

U+13000 = d80c dc00

最后一个是

U+1342E = d80d dc2e

给出了

re = /(\uD80C[\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E])+/g

t = document.getElementById("pyramid").innerHTML
document.write("<h1>Found</h1>" + t.match(re))
<div id="pyramid">

  some     	really    	old    	stuff    	    
  
  </div>

这是安装Noto Sans Egyptian Hieroglyphs时的样子:

enter image description here

其他语言

在支持UCS-4的平台上,您可以直接使用埃及代码点130001342F,但语法因系统而异。例如,在Python(3.3 up)中它将是[\U00013000-\U0001342E]

>>> s = "some \U+13000 really \U+13001 old \U+1342C stuff \U+1342D \U+1342E"
>>> s
'some  really  old  stuff  '
>>> import re
>>> re.findall('[\U00013000-\U0001342E]', s)
['', '', '', '', '']

最后,如果您的正则表达式引擎支持unicode属性,您可以(并且应该)使用这些而不是硬编码范围。例如在php / pcre中:

$str = " some  really  old  stuff   ";

preg_match_all('~\p{Egyptian_Hieroglyphs}~u', $str, $m);
print_r($m);

打印

[0] => Array
    (
        [0] => 
        [1] => 
        [2] => 
        [3] => 
        [4] => 
    )

答案 1 :(得分:10)

Unicode编码Egyptian hieroglyphs,范围为U + 13000 - U + 1342F(超出基本多语言平面)。

在这种情况下,有两种方法可以编写正则表达式:

  1. 通过指定U + 13000 - U + 1342F的字符范围。

    虽然在BMP中为字符指定正则表达式中的字符范围就像[a-z]一样简单,但根据语言支持,对星体平面中的字符这样做可能不那么简单。

  2. 通过为埃及象形文字指定Unicode块

    由于我们匹配埃及象形文字块中的任何字符,因此这是编写支持可用的正则表达式的首选方法。

  3. 的Java

    (目前,我还不知道Java类库的其他实现如何处理Pattern类中的星体平面字符。)

    Sun / Oracle实施

    我不确定在Java 1.4中讨论星体平面中匹配字符是否有意义,因为只有通过改进现有的String实现(使用UCS-2)才能在Java 5中添加对BMP之外的字符的支持。对于其内部字符串表示),使用代码点感知方法。

    由于Java继续允许在String中指定单独的代理(一个不能与其他代理形成一对),它导致一团糟,因为代理不是真正的字符,而且单独的代理在UTF-16中无效。

    Pattern类看到了从Java 1.4.x到Java 5的重大改进,因为该类被重写以支持在星体平面中匹配Unicode字符:模式字符串之前被转换为代码点数组它被解析,输入字符串由String类中的代码点感知方法遍历。

    You can read more about the madness in Java regex in this answer by tchist.

    我已经详细解释了如何匹配涉及星界平面字符in this answer的一系列角色,所以我只想在这里包含代码。它还包括一些错误尝试编写正则表达式以匹配星体平面字符的反例。

    Java 5(及以上)

    "[\uD80C\uDC00-\uD80D\uDC2F]"
    

    Java 7(及以上)

    "[\\uD80C\\uDC00-\\uD80D\\uDC2F]"
    "[\\x{13000}-\\x{1342F}]"
    

    由于我们匹配的任何代码点都属于Unicode块,因此它也可以写成:

    "\\p{InEgyptian_Hieroglyphs}"
    "\\p{InEgyptian Hieroglyphs}"
    "\\p{InEgyptianHieroglyphs}"
    
    "\\p{block=EgyptianHieroglyphs}"
    "\\p{blk=Egyptian Hieroglyphs}"
    

    自1.4以来,Java支持\p Unicode块的语法,但仅在Java 7中添加了对埃及象形文字块的支持。

    PCRE(在PHP中使用)

    PHP示例已涵盖在georg's answer中:

    '~\p{Egyptian_Hieroglyphs}~u'
    

    请注意,如果您希望按代码点匹配而不是按代码单位进行匹配,则u标志是必需的。

    不确定StackOverflow上是否有更好的帖子,但是I have written some explanation on the effect of u flag (UTF mode) in this answer of mine

    有一点需要注意,Egyptian_Hieroglyphs仅适用于PCRE 8.02(或不早于PCRE 7.90的版本)。

    作为替代方案,您可以使用\x{h...hh}语法指定字符范围:

    '~[\x{13000}-\x{1342F}]~u'
    

    请注意强制性u标记。

    至少PCRE 4.50支持\x{h...hh}语法。

    JavaScript(ECMAScript)

    ES5

    georg's answer已经涵盖了字符范围方法(这是在vanilla JavaScript中执行此操作的唯一方法)。修改正则表达式以覆盖整个块,包括保留的未分配代码点。

    /(?:\uD80C[\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2F])/
    

    上面的解决方案演示了匹配星体平面中一系列字符的技术,以及JavaScript RegExp的限制。

    JavaScript也遇到与Java相同的字符串表示问题。虽然Java确实在Java 5中修复了Pattern类以允许它使用代码点,但JavaScript RegExp仍然停留在UCS-2时代,迫使我们使用代码单元而不是代码点在正则表达式中。

    ES6

    最后,在ECMAScript 6中添加了对代码点匹配的支持,可通过u标志提供,以防止破坏以前版本的ECMAScript中的现有实现。

    点击上面第二个链接的Support部分,查看为ES6 RegExp提供实验支持的浏览器列表。

    在ES6中引入\u{h...hh}语法后,可以用类似于Java 7的方式重写字符范围:

    /[\u{13000}-\u{1342F}]/u
    

    或者您也可以直接在RegExp字面值中指定字符,但意图并不像[a-z]那样明确:

    /[-]/u
    

    请注意上面两个正则表达式中的u修饰符。

    还是被ES5困住了吗?不用担心,您可以使用regxpu将ES6 Unicode RegExp转换为ES5 RegExp。