/ bin / bash printf не работает с другими LANG, чем C - PullRequest
5 голосов
/ 13 января 2012

У меня действительно странная проблема с / bin / bash и скриптом, который использует printf для форматирования строки.

Мой скрипт выглядит так

rt=$(printf "%.3f" 13.234324245)

с той разницей, чтоЯ вычисляю число 13,23 ... выше.Когда я использую / usr / bin / zsh, это прекрасно работает!Даже / bin / sh может это сделать (но он не может выполнить if if ...) Самая большая проблема в том, что / bin / bash, похоже, не понимает printf или имеет другой способ форматирования, когда я не использую LANG=C.

Моя переменная LANG установлена ​​на de_AT.UTF-8, и тогда я получаю эту ошибку:

/path/to/script: Zeile 12: printf: 13.234324245: Ungültige Zahl.

Так что просто говорится, что число, которое я дал printf, недействительно ...

Нужно ли мне запускать printf по-другому?

edit: Кажется, проблема в вычислении числа:

rt=$(printf "%.3f" $(echo "$res2 - $res1"|bc ))

как я могу сказать bc использовать a, вместо .?

Ответы [ 4 ]

5 голосов
/ 13 января 2012

Ваша проблема связана с параметром LC_NUMERIC, который следует за bash при разборе аргументов на printf.

Я считаю это поведение сомнительным.Ksh93 также анализирует числа в соответствии с LC_NUMERIC, в то время как pdksh и dash хотят использовать точку в качестве разделителя в аргументе, а zsh принимает либо точку, либо локальный формат. POSIX не говорит, потому что указанный формат с плавающей запятой является необязательным в printf (хотя при печати чисел необходимо соблюдать LC_NUMERIC).

Как пользователь, я рекомендую никогда не устанавливатьLC_NUMERIC и LC_COLLATE за исключением особых случаев, когда вы уверены, что хотите их поведение.Это означает, что вы не используете LANG и не устанавливаете определенные категории;большинству людей нужны только LC_CTYPE (кодировка символов), LC_MESSAGES (язык сообщений) и LC_TIME (формат даты и времени).В сценарии вы можете переопределить все категории, установив LC_ALL, или определенную категорию, установив ее (настройка LANG только переопределяет $LANG, но не настраивается пользователем $LC_NUMERIC).

#!/bin/sh
LC_NUMERIC=C LC_COLLATE=C
printf "%.3f" 13.234324245
2 голосов
/ 13 января 2012

Просто выполните $(LANG=C printf "%.3f" 13.234324245), просто установите LANG для этой команды

2 голосов
/ 13 января 2012

Вероятно, это проблема локали - я думаю, что в немецком языке десятичный разделитель - запятая ,, а не точка .. Попробуйте использовать 13,234324245 в качестве значения.

1 голос
/ 13 января 2012

Вы можете использовать другие реализации printf: с не встроенным / usr / bin / printf:

% # LANG is ru_RU.UTF8, decimal separator is comma
% /usr/bin/printf %.3f 3.14
3,140
% /usr/bin/printf %.3f 3,14
/usr/bin/printf: 3,14: значение преобразовано не полностью
3,000
% LANG=C /usr/bin/printf %.3f 3,14
printf: 3,14: value not completely converted
3.00

С zsh встроенной реализацией printf:

% printf %.3f 3.14
3,140
% printf %.3f 3,14
3,140
...