在 unix 命令行上在 Unicode 规范化形式之间进行转换

glt*_*lts 30 command-line text-processing unicode conversion

在 Unicode 中,某些字符组合具有不止一种表示形式。

例如,字符ä可以表示为

  • “ä”,即代码点 U+00E4(c3 a4UTF-8 编码中的两个字节),或作为
  • “a?”,即两个代码点 U+0061 U+0308(61 cc 88UTF-8 中的三个字节)。

根据 Unicode 标准,这两种表示形式是等效的,但具有不同的“规范化形式”,请参阅UAX #15:Unicode 规范化形式

unix 工具箱里有各种文本转换工具,想到sedtriconv、 Perl 。如何在命令行上快速轻松地进行 NF 转换?

Gil*_*il' 30

您可以使用ICU 中uconv实用程序。规范化是通过音译实现的()。-x

$ uconv -x any-nfd <<<ä | hd
00000000  61 cc 88 0a                                       |a...|
00000004
$ uconv -x any-nfc <<<ä | hd
00000000  c3 a4 0a                                          |...|
00000003
Run Code Online (Sandbox Code Playgroud)

在 Debian、Ubuntu 和其他衍生产品上,uconv是在libicu-dev包中。在 Fedora、Red Hat 和其他衍生产品上,以及在 BSD 端口中,它都在icu包中。

  • @glts 我通过浏览 `uconv -L` 显示的列表找到了 `any-nfd`。 (2认同)

Nyk*_*kin 8

Pythonunicodedata在其标准库中有模块,它允许通过unicodedata.normalize()函数转换 Unicode 表示:

import unicodedata

s1 = 'Spicy Jalape\u00f1o'
s2 = 'Spicy Jalapen\u0303o'

t1 = unicodedata.normalize('NFC', s1)
t2 = unicodedata.normalize('NFC', s2)
print(t1 == t2) 
print(ascii(t1)) 

t3 = unicodedata.normalize('NFD', s1)
t4 = unicodedata.normalize('NFD', s2)
print(t3 == t4)
print(ascii(t3))
Run Code Online (Sandbox Code Playgroud)

使用 Python 3.x 运行:

$ python3 test.py
True
'Spicy Jalape\xf1o'
True
'Spicy Jalapen\u0303o'
Run Code Online (Sandbox Code Playgroud)

Python 不太适合 shell oneliners,但如果您不想创建外部脚本,则可以这样做:

$ python3 -c $'import unicodedata\nprint(unicodedata.normalize("NFC", "äa?äa?äa?"))'
ääääää
Run Code Online (Sandbox Code Playgroud)

对于 Python 2.x,您必须添加编码行 ( # -*- coding: utf-8 -*-) 并使用 u 字符将字符串标记为 Unicode:

$ python -c $'# -*- coding: utf-8 -*-\nimport unicodedata\nprint(unicodedata.normalize("NFC", u"äa?äa?äa?"))'
ääääää
Run Code Online (Sandbox Code Playgroud)