Chinaunix首页 | 论坛 | 博客
  • 博客访问: 471631
  • 博文数量: 142
  • 博客积分: 4126
  • 博客等级: 上校
  • 技术积分: 1545
  • 用 户 组: 普通用户
  • 注册时间: 2008-02-22 10:03
文章分类

全部博文(142)

文章存档

2011年(8)

2010年(7)

2009年(64)

2008年(63)

我的朋友

分类:

2008-12-15 17:21:02

1.1.1 提出问题

你有一个包含Unicode combining characters 的字符串,你想把里面含有的每一串Unicode combining characters都当作逻辑上的单个字符。
 
1.1.2 解决方案

在正则表达式中使用\X来进行处理
 
 

$string = "fac\x{0327}ade"; # "façade"

$string =~ /fa.ade/; # 失败

$string =~ /fa\Xade/; # 成功匹配


@chars = split(//, $string); # @chars中的7的字符

@chars = $string =~ /(.)/g; # 和上面相同

@chars = $string =~ /(\X)/g; # @chars中的6个字符(unicode算一个字符)

1.1.3 讨论

在Unicode里面,你可以把一个基本字符跟一个或以上的non-spacing字符合并起来,这些non-spacing字符通常是一些读音符号,比如重音啊,变音,tildas等。由于这些combined characters的存在,为了适应传统的字符系统,有多种方法可以写出这些字符。

举个例子,字符串"façade",要写出这个字符串可以在2个字符a之间写上\x{E7},\x{E7}是一个Latin1 (ISO 8859-1)里面的字符。这些字符在Perl的内部UTF-8编码下都可能会被编码成2个字节(每个字符),但是在计算字符个数的时候,这些由“\x{E7}”构成的字节还是要被当成一个字符看。

有另外一种痛苦(thornier)一点的写法:可以用另外2个Unicode来写出这个字符U+00E7,那就是一个一般的字符c,后面跟着\x{0327},U+0327表示的是一个non-spacing combining character,意思是回退到前一个字符,并在其底部加一个变音符号。

很多时候你想让Perl把这些拼合在一起的字符串(译注:指 c\x{0327})当成一个字符来看。但是这些字符(译注:指字符c跟字符\x{0327})本身就是一个字符,Perl的很多跟字符相关的操作都只会把它们分割开来看,这些操作包括substr,length,使用正则表达式里面的元字符比如/./或/[^abc]/。

在正则表达式里面,元数据\X 匹配一个扩展的Unicode拼合字符串(extended Unicode combining character sequence),\X相当于这样的正则(?:\PM\pM*), 写长点是这样的:

(?x:                # begin non-capturing group
        \PM         # one character without the M (mark) property,
                    #   such as a letter
        \pM         # one character that does have the M (mark) property,
                    #   such as an accent mark
        *           # and you can have as many marks as you want
)

不用\X的话就算是那些对字符串的简单操作也是不可靠的。想想上一节的例子:以字符为单位翻转字符串。这里用combining characters来表示变音符号,那么字符串"année" 和字符串"niño"则分别是"anne\x{301}e" and "nin\x{303}o",看下面代码:

 

for $word ("anne\x{301}e", "nin\x{303}o") {
    printf "%s simple reversed to %s\n", $word,
        scalar reverse $word;
    printf "%s better reversed to %s\n", $word,
        join("", reverse $word =~ /\X/g);
}
# $>année simple reversed to éenna

# $>année better reversed to eénna

# $>niño simple reversed to õnin

# $>niño better reversed to oñin

翻转的时候如果只是进行一般翻转的话,那个变音符号就会从一个字符跳到另外一个字符上面。那是因为combining character(译注:指\x{301}或者\x{303})是对它的前一个字符来起注音作用的,你把整个字符串翻转了,(译注:那么就变成对后一个字符其注音作用了)。原来字符串里面,如果把基本字符附加combining characters的字符串(译注:指e\x{301}或者n\x{303})当成一个整体,然后再翻转整个列表,就没有上面说的那个问题了。

1.2.4 参考

请参考vperlre(1)和vperluniintro(1);和大骆驼书15章;下一节也有介绍。

阅读(488) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~