viernes, 16 de septiembre de 2016

printf - Formatea e imprime datos

Al contrario que otros comandos de este capítulo, el comando printf no se usa con tuberías (no acepta entrada estándar) ni se usa frecuentemente en la línea de comandos (se usa principalmente en scripts). Entonces ¿Por qué es tan importante? Porque se usa mucho.

printf (de la frase "print formatted" - impresión formateada) fue desarrollado originalmente para el lenguaje de programación C y ha sido implementado en muchos lenguajes de programación incluyendo el shell. De hecho, en bash, printf está incluido.

printf funciona así:

printf "formato" argumentos

Se le da al comando una cadena que contiene una descripción del formato que se aplica a una lista de argumentos. El resultado formateado se envía a la salida estándar. Aquí hay un ejemplo trivial:

[me@linuxbox ~]$ printf "I formatted the string: %s\n" foo
I formatted the string: foo

La cadena de formato puede contener texto literal (como "He formateado la cadena:"), secuencias de escape (como \n, un carácter de nueva línea), y secuencias que comiencen con el carácter %, que se llaman especificaciones de conversion. En el ejemplo anterior, la especificación de conversión %s se usa para formatear la cadena "foo" y colocarla en la salida del comando. Aquí está de nuevo:

[me@linuxbox ~]$ printf "I formatted '%s' as a string.\n" foo
I formatted 'foo' as a string.

Como podemos ver, la especificación de conversión %s se reemplaza por la cadena "foo" en la salida del comando. Esta conversión se usa para formatear cadenas de datos. Hay otros especificadores para otros tipos de datos. Esta tabla lista los tipos de datos usados más frecuentemente:

Tabla 21-4: Especificadores de tipos de datos frecuentes en printf
Especificador Descripción
d Formatea un número como un entero decimal con signo.
f Formatea y manda a la salida un número en coma flotante.
o Formatea un entero como un número octal.
s Formatea una cadena.
x Formatea un entero como número hexadecimal usando a-f en minúsculas donde sea necesario.
X Lo mismo que x pero usa letras mayúsculas.
% Imprime un símbolo % literal (es decir, especifica "%%")

Probaremos el efecto de cada especificador de conversión en la cadena "380":

[me@linuxbox ~]$ printf "%d, %f, %o, %s, %x, %X\n" 380 380 380 380 380 380
380, 380.000000, 574, 380, 17c, 17C

Como hemos usado seis especificadores de conversión, también tenemos que añadir seis argumentos a printf para el proceso. Los seis resultados muestran el efecto de cada especificador.

Se pueden añadir varios componentes opcionales al especificador de conversión para ajustar la salida. Una especificación de conversión completa consiste en lo siguiente:

%[flags][width][.precision]conversion_specification

Múltiples componentes opcionales, cuando se usan, deben aparecer en el orden indicado arriba para que sean interpretados correctamente. Aquí tenemos una descripción de cada uno:

Tabla 21-5: Componentes de especificación de conversión de printf
Componente Descripción
flags Hay diferentes marcas (flags):
# - Usa el "formato alternativo" para la salida. Esto varía según el tipo de dato. Para conversión o (número octal), la salida es precedida con 0. Para conversiones x y X (números hexadecimales), la salida es precedida con 0x o 0X respectivamente.
0 - (cero) Rellena la salida con ceros. Esto significa que el campo se rellenará con ceros a la izquierda, como en "000380".
- - (guión) Alinea la salida a la izquierda. Por defecto, printf alinea a la derecha la salida.
' ' - (espacio) Produce un espacio delante para números positivos.
+ - (signo más) Pone signo a los números positivos. Por defecto, printf sólo pone signo a los números negativos.
width Un número especificando la anchura mínima del campo.
.precision Para número en coma flotante, especifica el número de dígitos de precisión a mostrar tras la coma. En conversión de cadenas, precision especifica el número de caracteres a mostrar.

Aquí tenemos algunos ejemplos de diferentes formatos en acción:

Tabla 21-6: Impresión de ejemplos de especificación de conversión
Argumento Formato Resultado Notas
380 "%d" 380 Formateo simple de un entero.
380 "%#x" 0x17c Entero formateado como un número hexadecinal usando la marca de "formato alternativo".
380 "%05d" 00380 Entero formateado con ceros a la izquierda (relleno) y una anchura mínima de campo de cinco caracteres.
380 "%05.5f" 380,00000 Número formateado como número en coma flotante con relleno y cinco posiciones decimales de precisión. Como la anchura de campo mínima especificada (5) es menor de la anchura real del número formateado, el relleno no tiene ningún efecto.
380 "%010.5f" 0380,00000 Incrementando la anchura mínima del campo a 10 el relleno es ahora visible.
380 "%+d" +380 La marca + pone signo a un número positivo.
380 "%-d" 380 La marca - alinea el formato a la izquierda.
abcdefghijk "%5s" abcedfghijk Una cadena formateada con un ancho de campo mínimo.
abcdefghijk "%.5s" abcde Aplicando precisión a una cadena, se trunca.

De nuevo, printf se usa principalmente en scripts donde se emplea para formatear datos tabulares, en lugar de usar la línea de comandos directamente. Pero sí que podemos ver cómo puede usarse para resolver varios problemas de formato. Primero, obtengamos varios campos separados por caracteres tabulador:

[me@linuxbox ~]$ printf "%s\t%s\t%s\n" str1 str2 str3
str1  str2    str3

Insertando \t (la secuencia de escape para un tabulador), logramos el efecto deseado. A continuación, algunos números con formato especial:

[me@linuxbox ~]$ printf "Line: %05d %15.3f Result: %+15d\n" 1071 3.14156295 32589
Line: 01071            3.142 Result:            +32589

Esto muestra el efecto del ancho mínimo de campo en el espaciado de los campos. O cómo formatear una pequeña página web:

[me@linuxbox ~]$ printf "<html>\n\t<head>\n\t\t<title>%s</title>\n\t</head>\n\t<body>\n\t\t<p>%s</p>\n\t</body>\n</html>\n" "Page Title" "Page Content"
<html>
    <head>
        <title>Page Title</title>
    </head>
    <body>
        <p>Page Content</p>
    </body>
</html>

No hay comentarios:

Publicar un comentario