Какой текущий десятичный разделитель?

29

Скажем, у меня есть сценарий оболочки POSIX, который

  1. должен работать в разных системах / средах, которые я не контролирую, и
  2. Необходимо удалить десятичный разделитель из строки, которая генерируется программой, которая учитывает настройки локали.

Как я могу определить десятичный разделитель самым общим способом?

gboffi
источник
Что за сценарий? Где это работает? Пожалуйста, обновите свой вопрос, чтобы на него можно было ответить.
X Тянь
@XTian Общий сценарий оболочки, работающий в системе Unix / Linux. ֎ Я намеренно поставил вопрос в самом общем виде, потому что меня интересует самый общий ответ, как я указал в последней строке моего вопроса.
ГБОБФИ
1
@ StéphaneChazelas POSIX скрипт! Честно, я забыл, что я использовал tcshв ..., о боже, вы определенно можете сказать, что я СТАРЫЙ !!!
ГБОБФИ
1
Разве вы не можете запустить строковую программу в LC_ALL=Cсреде?
Анхель
@ Анхель Да, конечно, я мог бы ...
ГБОБФИ

Ответы:

43

Спросите locale:

locale decimal_point

Это выведет десятичную точку с использованием текущих настроек локали.

Если вам нужен разделитель тысяч:

locale thousands_sep
Стивен Китт
источник
2
И, по крайней мере, с помощью localeGNU libc, locale -k LC_NUMERICчтобы перечислить все настройки локали в категории LC_NUMERIC.
Стефан Шазелас
3
@Kusalananda это часть POSIX .
Стивен Китт
3
@muru printf "%'f"сделает это для printfреализаций, которые поддерживают %f.
Стивен Китт
2
@muru Единственное известное мне встроенное устройство, которое может выводить десятичный разделитель, - это, printfа некоторые оболочки (например, dash) не поддерживают интернационализированный вывод. В другом ответе Стефан Шазелас пояснил в комментарии , что POSIX этого не требуется
gboffi
1
@ StefhenKitt Так и есть. Просто странно, что я не сталкивался с этим раньше. Это не помогает, что я в системе, где это использование localeне поддерживается.
Кусалананда
6

Если это zshсценарий оболочки, вы можете использовать $langinfoспециальный ассоциативный массив в zsh/langinfoмодуле:

zmodload zsh/langinfo
radix=$langinfo[RADIXCHAR]

(это соответствует стандарту nl_langinfo(RADIXCHAR), подробности смотрите man nl_langinfoв вашей системе; $langinfo[THOUSEP]разделитель тысяч).

В bashсценарии (также работающем zsh) вы сможете получить его, не разветвляя отдельный процесс с помощью printfвстроенного:

printf -v radix %.1f 1 && radix=${radix:1:1}

Чтобы преобразовать число из формата языкового стандарта пользователя в формат языкового стандарта C, с помощью оболочки ksh93 вы можете сделать это следующим образом:

$ locale title
German locale for Germany
$ x=1.123.456,78 ksh -c 'typeset -F x="$x"; LC_ALL=C; printf "%.23g\n" "$x"'
1123456.78
Стефан Шазелас
источник
Самый общий, это может быть? tmp=$(printf %.1f 0);tmp=${tmp#0};radix=${tmp%0}
ГБОБФИ
1
@gboffi, это будет работать в некоторых интернационализированных printfреализациях, которые поддерживают %f, но не все. %fподдержка не является обязательной для POSIX. printfИз dash, например , всегда использует.
Stéphane Chazelas
повторно dashне интернационализируется ... Я только что нашел , что ... так что самое общее решение прибегнуть к locale decimal_point, не так ли?
ГБОБФИ
@ gboffi, наверное. GNU awkтакже может интерпретировать числа в текущей локали в режиме POSIX (хотя не обрабатывает разделитель тысяч).
Стефан Шазелас