Awk降低以重音开头的字符串-支持外来字符
我有一个文件在一行中包含以下字符串:“Ávila” 我想得到这个输出:“ávila” 问题是awk的函数tolower仅在字符串不以重音开头时才起作用,我必须使用awk 例如,如果我做了awk'开始{print tolower(“Ávila”)},那么我得到的是“Ávila”,而不是“ávila”,这就是我所期望的Awk降低以重音开头的字符串-支持外来字符,awk,character-encoding,diacritics,Awk,Character Encoding,Diacritics,我有一个文件在一行中包含以下字符串:“Ávila” 我想得到这个输出:“ávila” 问题是awk的函数tolower仅在字符串不以重音开头时才起作用,我必须使用awk 例如,如果我做了awk'开始{print tolower(“Ávila”)},那么我得到的是“Ávila”,而不是“ávila”,这就是我所期望的 但是如果我做了awk'BEGIN{print tolower(“Castellón”)},那么我会得到“Castellón”对于给定的awk实现,要正确地处理非ASCII字符(外来字
但是如果我做了awk'BEGIN{print tolower(“Castellón”)},那么我会得到“Castellón”对于给定的
awk
实现,要正确地处理非ASCII字符(外来字母),它必须尊重活动区域设置的字符编码,这反映在(有效的)LC\u CTYPE
设置中(运行locale
查看它)
如今,大多数地区使用UTF-8编码,这是一种多字节按需编码,在ASCII范围内为单字节,并使用2到4个字节来表示所有其他Unicode字符。因此,对于要识别非ASCII(重音、外来)字母的给定
awk
实现,它必须能够将多个字节识别为单个字符
在主要的awk
实施中
- GNU Awk(
),一些Linux发行版上的默认版本gawk
- BSD
,也用于OS Xawk
- (
),基于Debian的Linux发行版(如Ubuntu)的默认版本mawk
LC\u CTYPE=C
:
$ echo ÁvilA | LC_CTYPE=C gawk '{print tolower($0)}'
Ávila # only ASCII char. A lowercased
实用建议:
- 要确定默认的
是什么实现,请运行awk
awk--version
- 对于Mawk,您将收到一条错误消息,因为它只支持使用
打印版本信息,但该错误消息将包含单词-W version
Mawk
- 对于Mawk,您将收到一条错误消息,因为它只支持使用
- If如果可能,安装并使用GNU Awk(并可选择将其设置为默认的
);它可用于大多数类似Unix的平台;例如:Awk
- 在基于Debian的平台上,如Ubuntu:
sudo-apt-get-install-gawk
- 在OS X上,使用:
brew安装gawk
- 在基于Debian的平台上,如Ubuntu:
- 如果您必须使用BSD Awk或Mawk,请使用上述
方法确保多字节UTF-8字符至少在未经修改的情况下通过。[1],但是外来字母将不会被识别为字母(因此在这种情况下不会被小写)LC_CTYPE=C
[1] OS X上的BSD Awk和Mawk(奇怪的是,后者不在Linux上)将UTF-8编码字符处理如下:
- 每个字节都被错误地解释为它自己的字符
- 如果忽略高位后,结果字节值落在ASCII大写字母范围内,
将添加到原始字节值以获得小写对应值32
是Unicode码点Á
,其UTF-8编码是2字节序列:U+00C1
0xC3 0x81
:删除高位(0xC3
)会产生0xC3&0x7F
,它被解释为ASCII字母0x43
,C
(32
)因此被添加到原始值,产生0x20
(0xE3
)0xC3+0x20
:删除高位(0x81
)会产生0x81&0x7F
,它不在ASCII大写字母的范围内(0x1
,65-90
),因此字节保持原样0x41-0x5a
- 实际上,第一个字节从
修改为0xC3
,而第二个字节保持不变;由于0xE3
不是正确的UTF-8编码字符,因此终端将打印0xC3 0x81
以发出信号?
bash-3.2$ echo "TOMÀS VICENÇ ROMÀ" |LC_CTYPE=C gawk '{ print tolower($0)}'
tomÀs vicenÇ romÀ
bash-3.2$ echo "TOMÀS VICENÇ ROMÀ" |LC_CTYPE=C gawk '{ print $0}'|tr '[:upper:]' '[:lower:]'
tomàs vicenç romà
使用gnu awk 4.0.1,我从
tolower(“Ávila”)
中得到了“ávila”。顺便说一下:问题与字符串中外来字符的位置无关(在您的第二个命令中,外来字母碰巧已经是小写的),但在某些awk
实现中,根本无法将非ASCII字母识别为字母。
bash-3.2$ echo "TOMÀS VICENÇ ROMÀ" |LC_CTYPE=C gawk '{ print tolower($0)}'
tomÀs vicenÇ romÀ
bash-3.2$ echo "TOMÀS VICENÇ ROMÀ" |LC_CTYPE=C gawk '{ print $0}'|tr '[:upper:]' '[:lower:]'
tomàs vicenç romà