|
1 | | -============================ |
2 | | -2.9 Unicode字符串转为标准正则式 |
3 | | -============================ |
| 1 | +=========================== |
| 2 | +2.9 将Unicode文本标准化 |
| 3 | +=========================== |
4 | 4 |
|
5 | 5 | ---------- |
6 | 6 | 问题 |
7 | 7 | ---------- |
8 | | -todo... |
| 8 | +你正在处理Unicode字符串,需要确保所有字符串在底层有相同的表示。 |
| 9 | + |
| 10 | +| |
9 | 11 |
|
10 | 12 | ---------- |
11 | 13 | 解决方案 |
12 | 14 | ---------- |
13 | | -todo... |
| 15 | +在Unicode中,某些字符能够用多个合法的编码表示。为了说明,考虑下面的这个例子: |
| 16 | + |
| 17 | +.. code-block:: python |
| 18 | +
|
| 19 | + >>> s1 = 'Spicy Jalape\u00f1o' |
| 20 | + >>> s2 = 'Spicy Jalapen\u0303o' |
| 21 | + >>> s1 |
| 22 | + 'Spicy Jalapeño' |
| 23 | + >>> s2 |
| 24 | + 'Spicy Jalapeño' |
| 25 | + >>> s1 == s2 |
| 26 | + False |
| 27 | + >>> len(s1) |
| 28 | + 14 |
| 29 | + >>> len(s2) |
| 30 | + 15 |
| 31 | + >>> |
| 32 | +
|
| 33 | +这里的文本"Spicy Jalapeño"使用了两种形式来表示。 |
| 34 | +第一种使用整体字符"ñ"(U+00F1),第二种使用拉丁字母"n"后面跟一个"~"的组合字符(U+0303)。 |
| 35 | + |
| 36 | +在需要比较字符串的程序中使用字符的多种表示会产生问题。 |
| 37 | +为了修正这个问题,你可以使用unicodedata模块先将文本标准化: |
| 38 | + |
| 39 | +.. code-block:: python |
| 40 | +
|
| 41 | + >>> import unicodedata |
| 42 | + >>> t1 = unicodedata.normalize('NFC', s1) |
| 43 | + >>> t2 = unicodedata.normalize('NFC', s2) |
| 44 | + >>> t1 == t2 |
| 45 | + True |
| 46 | + >>> print(ascii(t1)) |
| 47 | + 'Spicy Jalape\xf1o' |
| 48 | + >>> t3 = unicodedata.normalize('NFD', s1) |
| 49 | + >>> t4 = unicodedata.normalize('NFD', s2) |
| 50 | + >>> t3 == t4 |
| 51 | + True |
| 52 | + >>> print(ascii(t3)) |
| 53 | + 'Spicy Jalapen\u0303o' |
| 54 | + >>> |
| 55 | +
|
| 56 | +normalize()第一个参数指定字符串标准化的方式。 |
| 57 | +NFC表示字符应该是整体组成(比如可能的话就使用单一编码),而NFD表示字符应该分解为多个组合字符表示。 |
| 58 | + |
| 59 | +Python同样支持扩展的标准化形式NFKC和NFKD,它们在处理某些字符的时候增加了额外的兼容特性。比如: |
| 60 | + |
| 61 | +.. code-block:: python |
| 62 | +
|
| 63 | + >>> s = '\ufb01' # A single character |
| 64 | + >>> s |
| 65 | + 'fi' |
| 66 | + >>> unicodedata.normalize('NFD', s) |
| 67 | + 'fi' |
| 68 | + # Notice how the combined letters are broken apart here |
| 69 | + >>> unicodedata.normalize('NFKD', s) |
| 70 | + 'fi' |
| 71 | + >>> unicodedata.normalize('NFKC', s) |
| 72 | + 'fi' |
| 73 | + >>> |
| 74 | +
|
| 75 | +| |
14 | 76 |
|
15 | 77 | ---------- |
16 | 78 | 讨论 |
17 | 79 | ---------- |
18 | | -todo... |
| 80 | +标准化对于任何需要以一致的方式处理Unicode文本的程序都是非常重要的。 |
| 81 | +当处理来自用户输入的字符串而你很难去控制编码的时候尤其如此。 |
| 82 | + |
| 83 | +在清理和过滤文本的时候字符的标准化也是很重要的。 |
| 84 | +比如,假设你想清除掉一些文本上面的变音符的时候(可能是为了搜索和匹配): |
| 85 | + |
| 86 | +.. code-block:: python |
| 87 | +
|
| 88 | + >>> t1 = unicodedata.normalize('NFD', s1) |
| 89 | + >>> ''.join(c for c in t1 if not unicodedata.combining(c)) |
| 90 | + 'Spicy Jalapeno' |
| 91 | + >>> |
| 92 | +
|
| 93 | +最后一个例子展示了unicodedata模块的另一个重要方面,也就是测试字符类的工具函数。 |
| 94 | +combining()函数可以测试一个字符是否为组合字符。 |
| 95 | +在这个模块中还有其他函数用于查找字符类别,测试是否为数字字符等等。 |
| 96 | + |
| 97 | +Unicode显然是一个很大的主题。如果想更深入的了解关于标准化方面的信息, |
| 98 | +请看考`Unicode官网中关于这部分的说明 <http://www.unicode.org/faq/normalization.html>`_ |
| 99 | +Ned Batchelder在`他的网站 <http://nedbatchelder.com/text/unipain.html>`_ |
| 100 | +上对Python的Unicode处理问题也有一个很好的介绍。 |
| 101 | + |
0 commit comments