29

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 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 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 at 11:04
  • 1
    Can't you run the string-emitted program under a LC_ALL=C environment? – Ángel Sep 12 at 22:36
  • @Ángel Oh yes, of course I could... – gboffi Sep 13 at 6:02
43

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
  • 2
    And at least with the locale from the GNU libc, locale -k LC_NUMERIC to list all the locale settings in the LC_NUMERIC category. – Stéphane Chazelas Sep 12 at 10:32
  • 3
    @Kusalananda it’s part of POSIX. – Stephen Kitt Sep 12 at 10:56
  • 3
    @muru printf "%'f" would do it, for printf implementations which support %f. – Stephen Kitt Sep 12 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 at 11:18
  • 1
    @StephenKitt So it is. It's just odd that I haven't come across it before. It doesn't help that I'm on a system where that use of locale isn't supported. – Kusalananda Sep 12 at 12:34
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
  • Most generic, could it be? tmp=$(printf %.1f 0);tmp=${tmp#0};radix=${tmp%0} – gboffi Sep 12 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 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 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 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.