2010-12-07 10 views
32

Tengo un archivo generado automáticamente cada día que recibe un script de shell. embargo, el problema que estoy enfrentando es que el archivo generado automáticamente tiene una forma de:SPRINTF en shell scripting?

FILE_MM_DD.dat 

... donde MM y DD son meses 2 dígitos y cuerdas día-de-la-mes.

Investigué un poco y me di cuenta por mi cuenta, pero no sé cómo crear estas cadenas personalizadas usando solo scripts de shell.

Para que quede claro, soy consciente de la función FECHA en Bash, pero lo que estoy buscando es el equivalente de la función sprintf en C.

+0

Además, mi especificación requiere que genero cadenas como FILE_12_1.dat en lugar de FILE_12_01.dat cuando sea necesario. –

+0

Entonces el "DD" es falso. –

+1

Correcto, el DD no es parte de mi especificación, sino solo un atajo para explicar cosas. ¿Algunas ideas? –

Respuesta

42

En Bash:

var=$(printf 'FILE=_%s_%s.dat' "$val1" "$val2") 

o el equivalente, y más cerca de sprintf:

printf -v var 'FILE=_%s_%s.dat' "$val1" "$val2" 

Si las variables contienen valores decimales con ceros a la izquierda, puede eliminar los ceros a la izquierda :

val1=008; val2=02 
var=$(printf 'FILE=_%d_%d.dat' $((10#$val1)) $((10#$val2))) 

o

printf -v var 'FILE=_%d_%d.dat' $((10#$val1)) $((10#$val2)) 

El $((10#$val1)) coacciona el valor en la base 10 de modo que el %d en la especificación de formato no piensa que "08" es un valor octal válido.

Si está utilizando date (al menos para GNU date), se puede omitir los ceros como este:

date '+FILE_%-m_%-d.dat' 

Para completar, si desea añadir ceros a la izquierda, acolchado a una cierta anchura:

val1=8; val2=2 
printf -v var 'FILE=_%04d_%06d.dat' "$val1" "$val2" 

o con anchos dinámicos:

val1=8; val2=2 
width1=4; width2=6 
printf -v var 'FILE=_%0*d_%0*d.dat' "$width1" "$val1" "$width2" "$val2" 

Agregar ceros a la izquierda es útil para crear valores que se ordenan fácilmente y se alinean ordenadamente en columnas.

+0

Gracias Dennis. Esta es la solución más cercana que he visto hasta ahora. Y por más cercano, quiero decir perfecto :) –

+1

¡Citas! '" $ var1 "', '" $ var2 "', etc. Incluso sabiendo que los valores son numéricos, ¿qué pasa si hay dígitos en IFS? –

+1

@CharlesDuffy: Cotizaciones agregadas. Normalmente, tengo una función de supervisión que detecta si 'IFS' contiene dígitos o la existencia de otras condiciones no deseadas y, en caso afirmativo,' dd' ceros a todos los sistemas de archivos alcanzables. ;-) –

7

Por qué no usar el programa de printf coreutils?

$ printf "FILE_%02d_%02d.dat" 1 2 
FILE_01_02.dat 
+1

Gracias, halo. También acabo de encontrar esta opción: $ date "+ FILE_% m_% d" FILE_12_07 –

+0

Para ser claro, lo que me gustaría es un truncamiento de ceros a la izquierda, pero creo que puedo entenderlo desde el hombre de PRINTF página. –

+0

¿Qué quiere decir con "truncamiento de ceros a la izquierda"? Por favor explique y ofrecerá mis habilidades en printf o regex magic si es necesario ;-) Si encuentra la solución por su cuenta, por favor publique. Me interesaría entender lo que realmente necesitabas. –

1

Probar:

sprintf() { local stdin; read -d '' -u 0 stdin; printf "[email protected]" "$stdin"; } 

Ejemplo:

$ echo bar | sprintf "foo %s" 
foo bar