2012-01-13 11 views
5

Tengo un problema realmente extraño con/bin/bash y un script que utiliza printf para formatear una cadena./bin/bash printf no funciona con otro LANG que C

Mi script se parece a esto

rt=$(printf "%.3f" 13.234324245) 

con la diferencia, de que puedo calcular el número 13.23 ... arriba. ¡Cuando uso/usr/bin/zsh eso funciona genial! Incluso/bin/sh puede hacerlo (pero no puede hacer las cosas si ...) El mayor problema es que/bin/bash parece no entender printf o tiene otra forma de formateo cuando no uso LANG=C.

Mi LANG variable se establece en de_AT.UTF-8 y luego me sale este error:

/path/to/script: Zeile 12: printf: 13.234324245: Ungültige Zahl. 

Así que simplemente dice que el número i di printf no es válido ...

Qué necesito para ejecutar printf ¿de una manera diferente?

edición: El problema parece estar en el cálculo del número:

rt=$(printf "%.3f" $(echo "$res2 - $res1"|bc)) 

cómo puedo decirle bc utilizar un , en lugar de .?

Respuesta

4

Su problema se deriva de la configuración LC_NUMERIC, que sigue argumen fiesta cuando análisis sintáctico ts a printf.

Encuentro este comportamiento dudoso. Ksh93 también analiza números según LC_NUMERIC, mientras que pdksh y dash quieren un punto como separador en el argumento, y zsh acepta un punto o el formato local. POSIX no dice, porque el formato de punto flotante especificado es opcional en printf (LC_NUMERIC debe respetarse al imprimir números).

Como usuario, recomiendo nunca configurar LC_NUMERIC y LC_COLLATE excepto en circunstancias muy específicas en las que esté seguro de que desea su comportamiento. Esto significa no usar LANG y establecer categorías específicas en su lugar; la mayoría de la gente solo necesita LC_CTYPE (codificación de caracteres), LC_MESSAGES (idioma de los mensajes) y LC_TIME (formato de fecha y hora). En una secuencia de comandos, puede anular todas las categorías configurando LC_ALL o una categoría específica configurándola (la configuración LANG solo reemplaza a $LANG y no a un conjunto de usuarios $LC_NUMERIC).

#!/bin/sh 
LC_NUMERIC=C LC_COLLATE=C 
printf "%.3f" 13.234324245 
2

Probablemente sea un problema de configuración regional: creo que en alemán el separador decimal es una coma , en lugar del período .. Intente usar 13,234324245 como su valor.

+0

Eso es interesante –

+0

pero entonces, ¿cómo puedo hacer que cuando el flotador está viniendo de BC? sed? D: – reox

+0

Probablemente lo más fácil en este caso es usar la solución de @ J-16 y forzar LANG = C. –

2

Sólo hacer una $(LANG=C printf "%.3f" 13.234324245), acaba de establecer LANG en este comando

+2

Recomiendo configurar 'LC_NUMERIC' en lugar de' LANG', para anular también un conjunto de usuarios 'LC_NUMERIC'. O incluso 'LC_ALL' que los supera a todos. – Gilles

1

Se pueden usar otras implementaciones printf: con la no-incorporado/usr/bin/printf:

% # LANG is ru_RU.UTF8, decimal separator is comma 
% /usr/bin/printf %.3f 3.14 
3,140 
% /usr/bin/printf %.3f 3,14 
/usr/bin/printf: 3,14: значение преобразовано не полностью 
3,000 
% LANG=C /usr/bin/printf %.3f 3,14 
printf: 3,14: value not completely converted 
3.00 

Con zsh printf incorporado aplicación:

% printf %.3f 3.14 
3,140 
% printf %.3f 3,14 
3,140