在 awk 中更改 sprintf 的区域设置 (LC_ALL)

问题描述 投票:0回答:2

我想使用 sprintf("%c") 将 129 到 255 范围内的整数值打印到字符串中,并且对“GNU Awk 用户指南”中提到的以下语句有问题:

注意:POSIX 标准规定字符串的第一个字符是 打印。在具有多字节字符的语言环境中,gawk 尝试 将字符串的前导字节转换为有效的宽字符 然后打印该字符的多字节编码。相似地, 当打印数值时,gawk 允许该值在 可以用宽字符保存的数值范围。如果 转换为多字节编码失败,gawk 使用低八位 作为要打印的字符的值。

这会产生以下输出:

[:~]$ gawk 'BEGIN {retString = sprintf("%c%c%c", 129, 130, 131); print retString}' | od -x
0000000 81c2 82c2 83c2 000a

在每个字节(0x81、0x82、0x82)前面添加一个额外的字节(0xc2)。我可以通过将 LC_ALL 设置为 C:

来避免这种情况
[:~]$ LC_ALL=C gawk 'BEGIN {retString = sprintf("%c%c%c", 129, 130, 131); print retString}' | od -x
0000000 8281 0a83

现在的问题是:如何在 awk 内更改语言环境而不在 awk 脚本外部设置 LC_ALL?我想在多个系统上使用此脚本,并且不希望输出取决于默认区域设置。

或者是否有另一种方法可以在不调用 sprintf() 的情况下达到相同的结果?

awk locale
2个回答
0
投票

我认为最简单的方法是创建一个包装脚本

$ cat cawk
LC_ALL=C gawk "$@"

并使其可执行

$ chmod +x cawk

它的工作原理就像

gawk

$ ./cawk -v a=42 'BEGIN {print a}'
42

0
投票

只需保持

UTF-8
模式并执行


echo "..." | gawk -e '{

    offset = 2 * 3^3 * 4^5 # 0xD800

    for (x = 128; x < 256; x++)

        curr_byte = sprintf("%c", x + offset)  
}' 

这样您就可以访问所有 8 位字节,而无需修改区域设置或使用

gawk -b (byte mode)

只需确保偏移量在这两个范围内(因为

gawk
2^32
处进行未记录的环绕):


  • 0x    D800
    -
    0x      DF00
    (UTF-16 代理范围)

  • 0x 11 0000
    -
    0x FFFF FF00
    (剩余的 32 位空间 以上 Unicode 分配)


0xD800  :=    24^3    *    4
        :=    12^3    *    2^5
        :=     6^3    *    4^4
        :=     3^3    *    2^11
        :=     54     *    4^5

        := (236 + 20) * (236 - 20)

        :=     24     *   48^2 
        :=     6      *   96^2 
© www.soinside.com 2019 - 2024. All rights reserved.