首页 > 解决方案 > 在 awk 中更改 sprintf 的语言环境(LC_ALL)

问题描述

我想使用 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() 调用的情况下达到相同的结果?

标签: awklocale

解决方案


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

$ cat cawk
LC_ALL=C gawk "$@"

并使其可执行

$ chmod +x cawk

它的工作原理就像gawk

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

推荐阅读