34

Say I have a POSIX shell script that

  1. needs to run on different systems/environments that I do not control, and
  2. needs to remove the decimal separator from a string that is emitted by a program that respects the locale settings.

How can I detect the decimal separator in the most general way?

5
  • What sort of script ? Where is it running ? Please update your question, so that it can be answered.
    – X Tian
    Commented Sep 12, 2019 at 9:45
  • @XTian A generic shell script, that's running on a Unix/Linux system. ֎ I deliberately posed the question in the most general way because I'm interested in the most general answer, as I specified in the last line of my question.
    – gboffi
    Commented Sep 12, 2019 at 9:49
  • 1
    @StéphaneChazelas A POSIX script! Honest, I forgot that i used to use tcsh in ..., oh my, you definitely can say that I'm OLD!!!
    – gboffi
    Commented Sep 12, 2019 at 11:04
  • 2
    Can't you run the string-emitted program under a LC_ALL=C environment?
    – Ángel
    Commented Sep 12, 2019 at 22:36
  • @Ángel Oh yes, of course I could...
    – gboffi
    Commented Sep 13, 2019 at 6:02

2 Answers 2

51

Ask locale:

locale decimal_point

This will output the decimal point using the current locale settings.

If you need the thousands separator:

locale thousands_sep

You can view all the numeric keywords by requesting the LC_NUMERIC category:

locale -k LC_NUMERIC
3
  • Is there a way to have the number directly formatted using the current locale's decimal/thousands separators?
    – muru
    Commented Sep 12, 2019 at 10:57
  • 3
    @muru printf "%'f" would do it, for printf implementations which support %f. Commented Sep 12, 2019 at 11:05
  • 2
    @muru The only builtin that I know of, that can output a decimal separator, is printf and some shell (e.g., dash) do not support internationalized output. In another answer Stéphane Chazelas explained, in a comment, that it's not required by POSIX
    – gboffi
    Commented Sep 12, 2019 at 11:18
6

If that's a zsh shell script, you can use the $langinfo special associative array in the zsh/langinfo module:

zmodload zsh/langinfo
radix=$langinfo[RADIXCHAR]

(that maps to the standard nl_langinfo(RADIXCHAR), see man nl_langinfo on your system for details; $langinfo[THOUSEP] for the thousand separator).

In a bash script (would also work in zsh), you should be able to get it without forking a separate process using the printf builtin:

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

To convert a number from the user's locale format to the C locale format, with the ksh93 shell, you could do it like:

$ 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
4
  • Most generic, could it be? tmp=$(printf %.1f 0);tmp=${tmp#0};radix=${tmp%0}
    – gboffi
    Commented Sep 12, 2019 at 10:55
  • 1
    @gboffi, that would work in some internationalized printf implementations that support %f, but not all. %f support is not mandated by POSIX. The printf of dash for instance always uses . Commented Sep 12, 2019 at 10:57
  • re dash not internationalized... I've just found that... so the most general solution is resorting to locale decimal_point, isn't it?
    – gboffi
    Commented Sep 12, 2019 at 11:01
  • @gboffi, probably. GNU awk can also interpret numbers in the current locale with when in POSIX mode (doesn't handle the thousand separator though). Commented Sep 12, 2019 at 11:09

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .