¿Cuál es el separador decimal actual?

29

Digamos que tengo un script de shell POSIX que

  1. necesita ejecutarse en diferentes sistemas / entornos que no controlo, y
  2. necesita eliminar el separador decimal de una cadena emitida por un programa que respeta la configuración regional.

¿Cómo puedo detectar el separador decimal de la manera más general?

gboffi
fuente
¿Qué tipo de guión? A donde esta corriendo? Actualice su pregunta para que pueda ser respondida.
X Tian
@XTian Un script de shell genérico, que se ejecuta en un sistema Unix / Linux. ֎ Hice la pregunta deliberadamente de la manera más general porque estoy interesado en la respuesta más general, como especifiqué en la última línea de mi pregunta.
gboffi
1
@ StéphaneChazelas ¡Un script POSIX! Honestamente, olvidé que solía usar tcshen ... ¡oh, definitivamente puedes decir que soy VIEJO!
gboffi
1
¿No puede ejecutar el programa emitido por cadenas en un LC_ALL=Centorno?
Ángel
@ Ángel Oh sí, por supuesto que podría ...
gboffi

Respuestas:

43

pregunte locale:

locale decimal_point

Esto generará el punto decimal utilizando la configuración regional actual.

Si necesita el separador de miles:

locale thousands_sep
Stephen Kitt
fuente
2
Y al menos con el localede GNU libc, locale -k LC_NUMERICpara enumerar todas las configuraciones locales en la categoría LC_NUMERIC.
Stéphane Chazelas
3
@Kusalananda es parte de POSIX .
Stephen Kitt
3
@muru printf "%'f"lo haría, para printfimplementaciones que admitan %f.
Stephen Kitt
2
@muru La única BuiltIn que yo sepa, que la producción de lata un separador decimal, es printfy algunos shell (por ejemplo, dash) no soportan salida internacionalizado. En otra respuesta, Stéphane Chazelas explicó, en un comentario , que POSIX no lo requiere
gboffi
1
@StephenKitt Así es. Es extraño que no lo haya encontrado antes. No ayuda que esté en un sistema donde localeno se admite ese uso .
Kusalananda
6

Si se trata de un zshscript de shell, puede usar la $langinfomatriz asociativa especial en el zsh/langinfomódulo:

zmodload zsh/langinfo
radix=$langinfo[RADIXCHAR]

(que se asigna al estándar nl_langinfo(RADIXCHAR), consulte man nl_langinfoen su sistema para más detalles; $langinfo[THOUSEP]para el separador de miles).

En un bashscript (también funcionaría zsh), debería poder obtenerlo sin bifurcar un proceso separado usando el printfincorporado:

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

Para convertir un número del formato de configuración regional del usuario al formato de configuración regional C, con el shell ksh93, puede hacerlo de la siguiente manera:

$ 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
fuente
Más genérico, ¿podría ser? tmp=$(printf %.1f 0);tmp=${tmp#0};radix=${tmp%0}
gboffi
1
@gboffi, eso funcionaría en algunas printfimplementaciones internacionalizadas que admiten %f, pero no en todas. %fel soporte no es obligatorio por POSIX. El printfde dashpor ejemplo siempre usa.
Stéphane Chazelas
dashno estamos internacionalizados ... Acabo de descubrir que ... así que la solución más general es recurrir locale decimal_point, ¿no?
gboffi
@gboffi, probablemente. GNU awktambién puede interpretar números en el entorno local actual cuando está en modo POSIX (aunque no maneja el separador de miles).
Stéphane Chazelas