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?

  • What sort of script ? Where is it running ? Please update your question, so that it can be answered. – X Tian Sep 12 '19 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 Sep 12 '19 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 Sep 12 '19 at 11:04
  • 1
    Can't you run the string-emitted program under a LC_ALL=C environment? – Ángel Sep 12 '19 at 22:36
  • @Ángel Oh yes, of course I could... – gboffi Sep 13 '19 at 6:02

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
  • Is there a way to have the number directly formatted using the current locale's decimal/thousands separators? – muru Sep 12 '19 at 10:57
  • 3
    @muru printf "%'f" would do it, for printf implementations which support %f. – Stephen Kitt Sep 12 '19 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 Sep 12 '19 at 11:18

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

zmodload zsh/langinfo

(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"'
  • Most generic, could it be? tmp=$(printf %.1f 0);tmp=${tmp#0};radix=${tmp%0} – gboffi Sep 12 '19 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 . – Stéphane Chazelas Sep 12 '19 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 Sep 12 '19 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). – Stéphane Chazelas Sep 12 '19 at 11:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.