Quel est le séparateur décimal actuel?

29

Disons que j'ai un script shell POSIX qui

  1. doit fonctionner sur différents systèmes / environnements que je ne contrôle pas, et
  2. doit supprimer le séparateur décimal d'une chaîne émise par un programme qui respecte les paramètres régionaux.

Comment détecter le séparateur décimal de la manière la plus générale?

gboffi
la source
Quelle sorte de script? Où est-il en cours d'exécution? Veuillez mettre à jour votre question afin d'y répondre.
X Tian
@XTian Un script shell générique, qui s'exécute sur un système Unix / Linux. ֎ J'ai délibérément posé la question de la manière la plus générale car je suis intéressé par la réponse la plus générale, comme je l'ai précisé à la dernière ligne de ma question.
gboffi
1
@ StéphaneChazelas Un script POSIX! Honnêtement, j'ai oublié que j'avais l'habitude de l'utiliser tcshdans ..., oh mon Dieu, vous pouvez certainement dire que je suis vieux !!!
gboffi
1
Vous ne pouvez pas exécuter le programme émis par chaîne dans un LC_ALL=Cenvironnement?
Ángel
@ Ángel Oh oui, bien sûr que je pourrais ...
gboffi

Réponses:

43

Demandez locale:

locale decimal_point

Cela produira le point décimal en utilisant les paramètres régionaux actuels.

Si vous avez besoin du séparateur de milliers:

locale thousands_sep
Stephen Kitt
la source
2
Et au moins avec le localedu GNU libc, locale -k LC_NUMERICpour lister tous les paramètres régionaux dans la catégorie LC_NUMERIC.
Stéphane Chazelas
3
@Kusalananda fait partie de POSIX .
Stephen Kitt
3
@muru le printf "%'f"ferait, pour les printfimplémentations qui prennent en charge %f.
Stephen Kitt
2
@muru Le seul intégré que je connaisse, qui peut produire un séparateur décimal, est printfet certains shell (par exemple, dash) ne prennent pas en charge la sortie internationalisée. Dans une autre réponse Stéphane Chazelas a expliqué, dans un commentaire , que ce n'est pas requis par POSIX
gboffi
1
@StephenKitt Il en est ainsi. C'est juste étrange que je ne l'ai jamais rencontré auparavant. Cela n'aide pas que je sois sur un système où cette utilisation de localen'est pas prise en charge.
Kusalananda
6

S'il s'agit d'un zshscript shell, vous pouvez utiliser le $langinfotableau associatif spécial du zsh/langinfomodule:

zmodload zsh/langinfo
radix=$langinfo[RADIXCHAR]

(qui correspond à la norme nl_langinfo(RADIXCHAR), voir man nl_langinfosur votre système pour plus de détails; $langinfo[THOUSEP]pour le séparateur de milliers).

Dans un bashscript (fonctionnerait également dans zsh), vous devriez pouvoir l'obtenir sans bifurquer un processus séparé en utilisant le printfbuiltin:

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

Pour convertir un nombre du format local de l'utilisateur au format local C, avec le shell ksh93, vous pouvez le faire comme:

$ 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
Stéphane Chazelas
la source
Le plus générique, est-ce possible? tmp=$(printf %.1f 0);tmp=${tmp#0};radix=${tmp%0}
gboffi
1
@gboffi, cela fonctionnerait dans certaines printfimplémentations internationalisées qui prennent en charge %f, mais pas toutes. %fle support n'est pas mandaté par POSIX. Le printfof dashutilise par exemple toujours.
Stéphane Chazelas
re dashpas internationalisé ... Je viens de découvrir que ... donc la solution la plus générale est de recourir à locale decimal_point, non?
gboffi
@gboffi, probablement. GNU awkpeut également interpréter les nombres dans les paramètres régionaux actuels avec le mode POSIX (ne gère pas le séparateur de milliers cependant).
Stéphane Chazelas