изменение локали (LC_ALL) для sprintf внутри awk - PullRequest
0 голосов
/ 27 июня 2018

Я хочу вывести целочисленные значения в диапазоне от 129 до 255 в строку, используя sprintf ("% c"), и у меня возникла проблема со следующим оператором, упомянутым в "Руководстве пользователя 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, не устанавливая LC_ALL вне скрипта awk? Я хочу использовать этот скрипт в нескольких системах и не хочу, чтобы вывод зависел от настроек локали по умолчанию.

Или есть другой способ добиться того же результата без вызова sprintf ()?

1 Ответ

0 голосов
/ 27 августа 2018

Я думаю, что самый простой способ - создать скрипт-обертку

$ cat cawk
LC_ALL=C gawk "$@"

и сделайте его исполняемым

$ chmod +x cawk

Работает так же, как gawk

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