Qual é o separador decimal atual?

29

Digamos que eu tenha um script de shell POSIX que

  1. precisa ser executado em diferentes sistemas / ambientes que eu não controle e
  2. precisa remover o separador decimal de uma string emitida por um programa que respeite as configurações de localidade.

Como posso detectar o separador decimal da maneira mais geral?

gboffi
fonte
Que tipo de script? Para onde ele está funcionando? Atualize sua pergunta para que possa ser respondida.
X Tian
@XTian Um shell script genérico, que está sendo executado em um sistema Unix / Linux. Deliber Eu propositadamente fiz a pergunta da maneira mais geral, porque estou interessado na resposta mais geral, conforme especificado na última linha da minha pergunta.
gboffi 12/09
1
@ StéphaneChazelas Um script POSIX! Sinceramente, eu esqueci que eu costumava usar tcshem ... oh meu Deus, você definitivamente pode dizer que eu sou VELHO !!!
gboffi 12/09
1
Você não pode executar o programa emitido por string em um LC_ALL=Cambiente?
Ángel
@ Ángel Ah, sim, claro que eu poderia ...
gboffi 13/09

Respostas:

43

Pergunte locale:

locale decimal_point

Isso produzirá o ponto decimal usando as configurações atuais de localidade.

Se você precisar do separador de milhares:

locale thousands_sep
Stephen Kitt
fonte
2
E pelo menos com o localedo GNU libc, locale -k LC_NUMERICpara listar todas as configurações de localidade na categoria LC_NUMERIC.
Stéphane Chazelas 12/09
3
@Kusalananda faz parte do POSIX .
Stephen Kitt
3
O @muru printf "%'f"faria isso para printfimplementações suportadas %f.
Stephen Kitt
2
@muru A única embutido que eu saiba, que saída pode um separador decimal, é printfe alguns shell (por exemplo, dash) não suportam saída internacionalizada. Em outra resposta, Stéphane Chazelas explicou, em um comentário , que não é exigido pelo POSIX
gboffi 12/09
1
@StephenKitt Assim é. É estranho que eu nunca tenha encontrado isso antes. Não ajuda que eu esteja em um sistema em que esse uso localenão seja suportado.
Kusalananda
6

Se esse é um zshscript de shell, você pode usar a $langinfomatriz associativa especial no zsh/langinfomódulo:

zmodload zsh/langinfo
radix=$langinfo[RADIXCHAR]

(que mapeia para o padrão nl_langinfo(RADIXCHAR), consulte man nl_langinfoem seu sistema para obter detalhes; $langinfo[THOUSEP]para o separador de milhar).

Em um bashscript (também funcionaria zsh), você deve conseguir obtê-lo sem forjar um processo separado usando o printfbuiltin:

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

Para converter um número do formato de localidade do usuário para o formato de localidade C, com o shell ksh93, você pode fazer o seguinte:

$ 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
fonte
Mais genérico, poderia ser? tmp=$(printf %.1f 0);tmp=${tmp#0};radix=${tmp%0}
gboffi 12/09
1
@gboffi, isso funcionaria em algumas printfimplementações internacionalizadas que suportam %f, mas não em todas. %fO suporte não é obrigatório pelo POSIX. O printfde, dashpor exemplo, sempre usa.
Stéphane Chazelas
re dashnão internacionalizada ... Eu apenas encontrei que ... então a solução mais geral é recorrer a locale decimal_point, não é?
gboffi 12/09
@gboffi, provavelmente. O GNU awktambém pode interpretar números na localidade atual com o modo POSIX (embora não lide com o separador de milhar).
Stéphane Chazelas 12/09