我需要国际化实用程序执行与以下操作相同的操作tr
:从流中获取字符并将其替换为相应的字符。不需要像从下到上这样的特定案例解决方案,而是需要通用案例解决方案。如果可能的话,没有大猩猩管道sed
调用。
请注意,这tr
在 Linux 上不起作用:它转换字节,而不是字符。对于多字节编码,这会失败。
$ tr --version | head -n 1
tr (GNU coreutils) 8.23
$ echo $LC_CTYPE
en_US.UTF-8
$ echo 'Ångstrom' | tr Æ Œ
Ņngstrom
答案1
GNUsed
确实可以处理多字节字符。所以:
$ echo é½Æ | sed 'y/é½Æ/ABŒ/'
ABŒ
与其说 GNUtr
还没有国际化,不如说它不支持多字节字符(如 UTF-8 语言环境中的非 ASCII 字符)。 GNUtr
可以使用Æ
,Œ
只要它们是像 iso8859-15 字符集中那样的单字节。
更多相关信息,请访问如何让 tr 识别非 ascii(unicode) 字符?
无论如何,这与Linux无关,而是tr
与系统上的实现有关。该系统是否使用 Linux 作为内核、tr
为 Linux 构建或使用 Linux 内核 API 并不重要,因为这部分tr
功能发生在用户空间中。
busyboxtr
和 GNUtr
是为 Linux 构建的软件发行版中最常见的,并且不支持多字节字符,但是还有其他一些已移植到 Linux 的软件,例如tr
heirloom toolchest(从 OpenSolaris 移植)或 ast-打开那个做。
请注意,sed
'sy
不支持像a-z
.另请注意,如果包含的脚本sed 'y/é½Æ/ABŒ/'
是用 UTF-8 字符集编写的,则在非 UTF-8 字符集的语言环境中调用该脚本将不再按预期工作。
另一种方法是使用perl
:
perl -Mopen=locale -Mutf8 -pe 'y/a-zé½Æ/A-ZABŒ/'
上面,perl 代码预计采用 UTF-8,但它将处理区域设置编码中的输入(以及相同编码中的输出)。如果在 UTF-8 语言环境中调用,它将把 UTF-8 Æ
(0xc3 0x86) 音译为 UTF-8 Œ
(0xc5 0x92),在 ISO8859-15 中则相同,但对于 0xc6 -> 0xbc。
在大多数 shell 中,即使在 UTF-8 不是字符集的语言环境中调用脚本,在单引号内包含这些 UTF-8 字符也应该没问题(例外情况是,yash
如果这些字节不形成有效字符,则会报错在语言环境中)。但是,如果您使用单引号以外的其他引用,则可能会导致问题。例如,
perl -Mopen=locale -Mutf8 -pe "y/♣\`/&'/"
在字符集为 BIG5-HKSCS 的语言环境中会失败,因为 (0x5c) 的编码\
也恰好包含在其他一些字符中(例如α
:0xa3 0x5c,而 UTF-8 编码♣
恰好以 0xa3 结尾)。
无论如何,不要期望像这样的事情
perl -Mopen=locale -Mutf8 -pe 'y/Á-Ź/A-Z/'
努力消除尖锐的口音。以上其实只是
perl -Mopen=locale -Mutf8 -pe 'y/\x{c1}-\x{179}/\x{41}-\x{5a}/'
也就是说,范围基于 unicode 代码点。因此,范围在恰好位于“”中的定义明确的序列之外没有用处。正确的“Unicode 中的顺序如A-Z
, 0-9
.
如果您想删除尖锐的口音,您必须使用更高级的工具,例如:
perl -Mopen=locale -MUnicode::Normalize -pe '
$_ = NFKD($_); s/\x{301}//g; $_ = NFKC($_)'
即使用Unicode规范化形式来分解字符,去除重音符号(这里是组合形式U+0301
)并重新组合。
音译 Unicode 的另一个有用工具uconv
来自重症监护室。例如,上式也可以写成:
uconv -x '::NFKD; \u0301>; ::NFKC;'
但仅适用于 UTF-8 数据。你需要:
iconv -t utf-8 | uconv -x '::NFKD; \u0301>; ::NFKC;' | iconv -f utf-8
能够在用户的区域设置中处理数据。
答案2
在 Bash 中,您可以使用参数扩展。
替换Å
成功:
$ string='Hello Ångstrom'
$ a='Å'
$ b='Œ'
$ printf '%s\n' "${string//${a}/${b}}"
Hello Œngstrom
尝试替换Æ
,它不是字符串的一部分:
$ string='Hello Ångstrom'
$ a='Æ'
$ b='Œ'
$ printf '%s\n' "${string//${a}/${b}}"
Hello Ångstrom
答案3
这可能是你的编码方案。尝试通过 iconv 运行它,如下所示:
echo Ångstrom | iconv -f UTF-8 | tr 'Å' 'Œ'
推出: Œngstrom