viernes, 30 de septiembre de 2016

Impresión

Tras pasar el último par de capítulos manipulando texto, es hora de poner ese texto en un papel. En este capítulo, veremos las herramientas de línea de comandos que se usan para imprimir archivos y controlar el funcionamiento de la impresora. No veremos cómo configurar la impresión, ya que varía según la distribución y normalmente se configura automáticamente durante la instalación. Fíjate que necesitaremos un impresora funcionando y configurada para realizar los ejercicios de este capítulo.

Veremos los siguientes comandos:
  • pr - Convierte archivos de texto para imprimir
  • lpr - Imprime archivos
  • a2ps - Formatea archivos para imprimir en una impresora PostScript
  • lpstat - Muestra la información de estado de la impresora
  • lpq - Muestra el estado de la cola de impresión
  • lprm - Cancela trabajos de impresión

lunes, 26 de septiembre de 2016

Resumiendo

Dado que el texto es tan fundamental en la naturaleza de los sistemas operativos tipo Unix, tiene sentido que haya muchas herramientas que se usan para manipular y formatear texto. Como hemos visto, ¡Las hay! Las herramientas de formateo simple como fmt y pr encontrarán muchos usos en scripts que producen documentos cortos, mientras que groff (y sus amigos) pueden usarse para escribir libros. Puede que nunca escribamos un documento técnico usando herramientas de línea de comandos (¡Aunque hay mucha gente que lo hace!), pero es bueno saber que podríamos.

viernes, 23 de septiembre de 2016

groff

groff es una colección de programas que contiene la implementación GNU de troff. También incluye un script que se usa para emular nroff y al resto de la familia roff.

Si bien roff y sus descendientes se usan para crear documentos formateados, lo hacen de una forma algo extraña para los usuarios modernos. La mayoría de los documentos de hoy en día se producen usando procesadores de texto que pueden realizar tanto la composición como el formateado de un documento en un único paso. Antes de la llegada de los procesadores de texto gráficos, los documentos a menudo se producían en un proceso en dos pasos que incluía el uso de un editor de texto para realizar la composición, y un procesador, como troff, para realizar el formateo. Las instrucciones para el programa de formateo estaban incluidas en el texto compuesto a través del uso de un lenguaje de marcas. La analogía moderna para este tipo de procesos es la página web, que se crea usando un editor de texto de algún tipo y luego se renderiza usando un navegador web con HTML como lenguaje de marcas para describir el aspecto final de la página.

No vamos a ver groff en su totalidad, ya que muchos elementos de su lenguaje de marcas tienen que ver con detalles de tipografía muy arcanos. En su lugar nos concentraremos en uno de sus macro paquetes que se sigue usando ampliamente. Los macro paquetes concentran muchos de sus comandos de bajo nivel en una colección más pequeña de comandos de alto nivel que hace el uso de groff mucho más sencillo.

Por un momento, consideremos la humilde man page. Se encuentra en el directorio /usr/share/man como un archivo de texto comprimido con gzip. Si fuéramos a examinar su contenido descomprimido, veríamos lo siguiente (se muestra la man page de ls en su sección 1):

[me@linuxbox ~]$ zcat /usr/share/man/man1/ls.1.gz | head
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.35.
.TH LS "1" "April 2008" "GNU coreutils 6.10" "User Commands"
.SH NAME
ls \- list directory contents
.SH SYNOPSIS
.B ls
[\fIOPTION\fR]... [\fIFILE\fR]...
.SH DESCRIPTION
.\" Add any additional description here
.PP

Comparada a la man page en su presentación normal, podemos empezar a ver una correlación entre el lenguaje de marcas y su resultado:

[me@linuxbox ~]$ man ls | head
LS(1)           User Commands             LS(1)


NAME
         ls - list directory contents

SYNOPSIS
         ls [OPTION]... [FILE]...

La razón por la que esto es interesante es que las man pages están renderizadas por groff, usando el macro paquete man-doc. De hecho, podemos simular el comando man con la siguiente tubería:

[me@linuxbox ~]$ zcat /usr/share/man/man1/ls.1.gz | groff -mandoc -T ascii | head
LS(1)           User Commands             LS(1)


NAME
         ls - list directory contents
SYNOPSIS
         ls [OPTION]... [FILE]...

Aquí usamos el programa groff con las opciones configuradas para especificar el macro paquete mandoc y el controlador de salida para ASCII. groff puede producir salida en varios formatos. Si no se especifica ningún formato, la salida por defecto es PostScript:

[me@linuxbox ~]$ zcat /usr/share/man/man1/ls.1.gz | groff -mandoc | head
%!PS-Adobe-3.0
%%Creator: groff version 1.18.1
%%CreationDate: Thu Feb 5 13:44:37 2009
%%DocumentNeededResources: font Times-Roman
%%+ font Times-Bold
%%+ font Times-Italic
%%DocumentSuppliedResources: procset grops 1.18 1
%%Pages: 4
%%PageOrder: Ascend
%%Orientation: Portrait

Hemos mencionado brevemente PostScript en el capítulo anterior, y lo haremos de nuevo en el próximo capítulo. PostScript es un lenguaje de descripción de página que se usa para describir el contenido de una página impresa en un dispositivo tipográfico. Si tomamos la salida de nuestro comando y lo almacenamos en un archivo (asumiendo que estamos usando un entorno gráfico con un directorio Desktop):

[me@linuxbox ~]$ zcat /usr/share/man/man1/ls.1.gz | groff -mandoc > ~/Desktop/foo.ps

Un icono del archivo de salida aparecerá en el escritorio. Haciendo doble clic en el icono, se abrirá un visor de páginas y mostrará el archivo en su forma renderizada:

Figura 4: Viendo la salida PostScript con un visor de páginas en GNOME

Lo que vemos es ¡una bonita man page de ls! De hecho, es posible convertir el archivo PostScript a PDF (Portable Document Format - Formato de Documento Portable) con este comando:

[me@linuxbox ~]$ ps2pdf ~/Desktop/foo.ps ~/Desktop/ls.pdf

El programa ps2pdf es parte del paquete ghostscript, que está instalado en la mayoría de los sistemas Linux que soportan impresión:

Consejo: Los sistemas Linux a menudo incluyen muchos programas de línea de comandos para conversión de formatos de archivos. A menudo se nombran usando la convención format2format. Prueba a usar el comando ls /usr/bin/*[[:alpha:]]2[[:alpha:]]* para identificarlos. Prueba también a buscar programas llamados formattoformat.

Para nuestro último ejercicio con groff, volveremos a visitar a nuestro viejo amigo distros.txt una vez más. Esta vez, usaremos el programa tbl que se usa para formatear tablas para componer nuestra lista de distribuciones Linux. Para hacerlo, vamos a usar nuestro anterior script de sed para añadir etiquetas a una secuencia de texto que luego enviaremos a groff.

Primero, necesitamos modificar nuestro script sed para añadir las exigencias necesarias que requiere tbl. Usando un editor de texto, cambiaremos distros.sed a lo siguiente:

# sed script to produce Linux distributions report
1 i\
.TS\
center box;\
cb s s\
cb cb cb\
l n c.\
Linux Distributions Report\
=\
Name Version Released\
_
s/\([0-9]\{2\}\)\/\([0-9]\{2\}\)\/\([0-9]\{4\}\)$/\3-\1-\2/
$ a\
.TE

Fíjate que para que el script funcione correctamente, hay que tener cuidado y comprobar que las palabras "Name Version Released" estén separadas por tabuladores, no por espacios. Guardaremos el archivo resultante como distros-tbl.sed. tbl usa las etiquetas .TS y .TE para comenzar y finalizar la tabla. Las filas que siguen a la etiqueta .TS definen las propiedades globales de la tabla que, en nuestro ejemplo, están centradas horizontalmente en la página y rodeadas por una caja. Las restantes líneas de la definición describen el estilo de cada fila de la tabla. Ahora, si ejecutamos nuestro informe canalizándolo, otra vez, al nuevo script de sed, tendremos lo siguiente:

[me@linuxbox ~]$ sort -k 1,1 -k 2n distros.txt | sed -f distros-tbl.sed | groff -t -T ascii 2>/dev/null
          +------------------------------+
          | Linux Distributions Report   |
          +------------------------------+
          | Name    Version    Released  |
          +------------------------------+
          |Fedora     5       2006-03-20 |
          |Fedora     6       2006-10-24 |
          |Fedora     7       2007-05-31 |
          |Fedora     8       2007-11-08 |
          |Fedora     9       2008-05-13 |
          |Fedora    10       2008-11-25 |
          |SUSE      10.1     2006-05-11 |
          |SUSE      10.2     2006-12-07 |
          |SUSE      10.3     2007-10-04 |
          |SUSE      11.0     2008-06-19 |
          |Ubuntu     6.06    2006-06-01 |
          |Ubuntu     6.10    2006-10-26 |
          |Ubuntu     7.04    2007-04-19 |
          |Ubuntu     7.10    2007-10-18 |
          |Ubuntu     8.04    2008-04-24 |
          |Ubuntu     8.10    2008-10-30 |
          +------------------------------+

Añadiendo la opción -t a groff le ordenamos que pre-procese la secuencia de texto con tbl. De igual forma, la opción -T se usa para salida ASCII en lugar del medio de salida por defecto, PostScript.

El formato de la salida es el mejor que podemos esperar si estamos limitados por las capacidades de una pantalla de terminal o una impresora tipo máquina de escribir. Si especificamos salida PostScript y vemos gráficamente la salida resultante, tenemos un resultado más satisfactorio:

[me@linuxbox ~]$ sort -k 1,1 -k 2n distros.txt | sed -f distros-tbl.sed | groff -t > ~/Desktop/foo.ps


Figura 5: Viendo la tabla finalizada

lunes, 19 de septiembre de 2016

Sistemas de formateo de documentos

Hasta ahora, hemos examinado las herramientas simples de formato de texto. Son buenas para tareas simples y pequeñas, pero ¿qué pasa con grandes trabajos? Una de las razones que hizo que Unix llegara a ser un sistema operativo popular entre usuarios técnicos y científicos (además de proporcionar un poderoso entorno multitarea y multiusuario para todo tipo de desarrollo de software) es que ofrecía herramientas que podían usarse para producir muchos tipos de documentos, particularmente publicaciones científicas y académicas. De hecho, como la documentación GNU describe, la preparación de documentos era fundamental para el desarrollo de Unix:

La primera versión de UNIX fue desarrollada en un PDP-7 que estaba instalado en los Laboratorios Bell. En 1971 los desarrolladores querían conseguir un PDP-11 para seguir trabajando en el sistema operativo. Para justificar el coste de este sistema, propusieron que implementarían un sistema de formateo de documentos para la división de patentes de AT&T. Este primer programa de formateo fue una reimplementación del McIllroy's 'roff', escrito por J. F. Ossanna.

Dos principales familias de formateadores de documentos dominan el terreno: los descendientes del programa roff original, incluyendo nroff y troff, y aquellos basados en el sistema de composición tipográfica TEX (pronunciado "tek") de Donald Knuth. Y sí, la "E" caída en el centro es parte del nombre.

El nombre "roff" deriva del término "run off" como en, "I'll run off a copy for you. - Imprimiré una copia para tí". El programa nroff se usa para formatear documentos para su salida a dispositivos que usan fuentes monoespaciadas, como los terminales de caracteres e impresoras estilo máquina de escribir. En el momento de su introducción, esto incluía casi todos los dispositivos de impresión conectados a ordenadores. El posterior programa troff formatea documentos para salida a tipógrafos, dispositivos usados para producir escritura "lista para reproducción" para impresión comercial. La mayoría de las impresoras de ordenadores hoy en día pueden simular la salida de los tipógrafos. La familia roff también incluye algunos otros programas que se usan para preparar porciones de documentos. Estos incluyen eqn (para ecuaciones matemáticas) y tbl (para tablas).

El sistema TEX (en su forma estable) apareció por primera vez en 1989 y, hasta cierto punto, desplazó a troff como la herramienta elegida para salida a tipógrafos. No veremos TEX aquí, debido a su complejidad (hay libros enteros sobre él) y al hecho de que no viene instalado por defecto en la mayoría de los sistemas Linux modernos.

Consejo: Para aquellos interesados en instalar TEX, prueba el paquete texlive que puede encontrarse en la mayoría de los repositorios de las distribuciones, y el editor de contenido gráfico LyX.

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>

viernes, 9 de septiembre de 2016

pr - Formatea texto para imprimir

El programa pr se usa para paginar texto. Cuando imprimimos texto, a menudo es deseable separar las páginas de la salida con varias líneas en blanco, para darle un margen superior e inferior a cada página. Además, este espacio en blanco puede usarse para insertar un encabezado y un pie de página en cada página.

Probaremos pr formateando el archivo distros.txt en una serie de páginas muy cortas (sólo se muestran las dos primeras páginas):

[me@linuxbox ~]$ pr -l 15 -w 65 distros.txt



2008-12-11 18:27    distros.txt     Page 1



SUSE    10.2      12/07/2006
Fedora  10        11/25/2008
SUSE    11.0      06/19/2008
Ubuntu  8.04      04/24/2008
Fedora  8         11/08/2007



2008-12-11 18:27    distros.txt     Page 2



SUSE    10.3      10/04/2007
Ubuntu  6.10      10/26/2006
Fedora  7         05/31/2007
Ubuntu  7.10      10/18/2007
Ubuntu  7.04      04/19/2007

En este ejemplo, empleamos la opción -l (para la longitud de página) y la opción -w (ancho de página) para definir una "página" de 65 columnas de ancho y 15 líneas de largo. pr pagina el contenido del archivo distros.txt, separando cada página con varias líneas en blanco y crea un encabezado por defecto que contiene la fecha de modificación del archivo, el nombre del archivo y el número de página. El programa pr ofrece muchas opciones para controlar el diseño de página. Echaremos un vistazo más a fondo en el siguiente capítulo.

miércoles, 7 de septiembre de 2016

fmt - Un formateador de texto simple

El programa fmt también maqueta el texto, pero un poco más. Acepta tanto archivos como entrada estándar y realiza formateo de párrafos en la secuencia de texto. Básicamente, rellena y junta líneas de texto mientras que mantiene líneas en blanco y sangrías.

Para demostrarlo, necesitaremos algún texto. Tomemos algo de la página info de fmt:

    `fmt' reads from the specified FILE arguments (or standard input if none are given), and writes to standard output.

    By default, blank lines, spaces between words, and indentation are preserved in the output; successive input lines with different indentation are not joined; tabs are expanded on input and introduced on output.

    `fmt' prefers breaking lines at the end of a sentence, and tries to avoid line breaks after the first word of a sentence or before the last word of a sentence. A "sentence break" is defined as either the end of a paragraph or a word ending in any of `.?!', followed by two spaces or end of line, ignoring any intervening parentheses or quotes. Like TeX, `fmt' reads entire "paragraphs" before choosing line breaks; the algorithm is a variant of that given by Donald E. Knuth and Michael F. Plass in "Breaking Paragraphs Into Lines", `Software--Practice & Experience' 11, 11 (November 1981), 1119-1184.

Copiaremos este texto en nuestro editor de texto y guardaremos el archivo como fmt-info.txt. Ahora, digamos que queremos reformatear este texto para ajustarlo a una columna de cincuenta caracteres de ancho. Podríamos hacerlo procesando el archivo con fmt y la opción -w:

[me@linuxbox ~]$ fmt -w 50 fmt-info.txt | head
   `fmt' reads from the specified FILE arguments
   (or standard input if
none are given), and writes to standard output.

   By default, blank lines, spaces between words,
   and indentation are
preserved in the output; successive input lines
with different indentation are not joined; tabs
are expanded on input and introduced on output.

Bien, es un resultado poco manejable. Quizá deberíamos leer realmente este texto, ya que explica lo que está pasando:

Por defecto, las líneas en blanco, los espacios entre palabras y las sangrías se mantienen en la salida; las líneas de entrada sucesivas con diferentes sangrías no se unen; las tabulaciones se expanden en la entrada y se pasan a la salida.

Así que, fmt mantiene la sangría de la primera línea. Afortunadamente, fmt proporciona una opción para corregir ésto:

[me@linuxbox ~]$ fmt -cw 50 fmt-info.txt
   `fmt' reads from the specified FILE arguments
(or standard input if none are given), and writes
to standard output.

   By default, blank lines, spaces between words,
and indentation are preserved in the output;
successive input lines with different indentation
are not joined; tabs are expanded on input and
introduced on output.

   `fmt' prefers breaking lines at the end of a
sentence, and tries to avoid line breaks after
the first word of a sentence or before the
last word of a sentence. A "sentence break"
is defined as either the end of a paragraph
or a word ending in any of `.?!', followed
by two spaces or end of line, ignoring any
intervening parentheses or quotes. Like TeX,
`fmt' reads entire "paragraphs" before choosing
line breaks; the algorithm is a variant of
that given by Donald E. Knuth and Michael F.
Plass in "Breaking Paragraphs Into Lines",
`Software--Practice & Experience' 11, 11
(November 1981), 1119-1184.

Mucho mejor. Añadiendo la opción -c, ahora tenemos el resultado deseado.

fmt tiene algunas opciones interesantes:

Tabla 21-3: Opciones fmt
Opción Descripción
-c Opera en modo margen de corona (crown margin mode). Esto preserva la sangría de las dos primeras líneas de un párrafo. Las siguientes líneas se alinean con la sangría de la segunda línea.
-p string Solo formatea aquellas líneas que comienzan con el prefijo string. Tras formatear, el contenido de string se antepone a cada línea reformateada. Esta opción puede usarse para formatear texto en comentarios de código fuente. Por ejemplo, cualquier lenguaje de programación o archivo de configuración que use un carácter "#" para delimitar un comentario podría formatearse especificando -p '# ' de forma que sólo los comentarios se formatearán. Mira el ejemplo a continuación.
-s Modo sólo-división. En este modo, las líneas sólo se dividirán para ajustarse al ancho especificado de columna. Las líneas cortas no se unirán para rellenar líneas. Este modo es útil cuando formateamos texto de tipo código donde no queremos que se unan las líneas.
-u Realiza espaciado uniforme. Esto aplicará el estilo tradicional de "máquina de escribir" al texto. Esto significa que se aplica un espacio entre palabras y dos espacios entre frases. Este modo es útil para eliminar la "justificación", es decir, el texto que se ha rellenado con espacios para forzar la alineación tanto en el margen derecho como izquierdo.
-w ancho Formatea el texto para ajustarlo a un ancho de columna en caracteres. La opción por defecto es 75 caracteres. Nota: fmt en realidad formatea líneas ligeramente más cortas que el ancho especificado para permitir el equilibrio entre líneas.

La opción -p es particularmente interesante. Con ella, podemos formatear fragmentos seleccionados de un archivo, siempre que las líneas a formatear comiencen con la misma secuencia de caracteres. Muchos lenguajes de programación usan el símbolo de la almohadilla (#) para indicar el comienzo de un comentario y así pueden ser formateados usando esta opción. Creemos un archivo que simule un programa que use comentarios:

[me@linuxbox ~]$ cat > fmt-code.txt
# This file contains code with comments.

# This line is a comment.
# Followed by another comment line.
# And another.

This, on the other hand, is a line of code.
And another line of code.
And another.

Nuestro archivo de ejemplo contiene comentarios que comienzan con la cadena "# " (una # seguida por un espacio) y líneas de "código" que no. Ahora, usando fmt, podemos formatear los comentarios y dejar el código intacto:

[me@linuxbox ~]$ fmt -w 50 -p '# ' fmt-code.txt
# This file contains code with comments.

# This line is a comment. Followed by another
# comment line. And another.

This, on the other hand, is a line of code.
And another line of code.
And another.

Fíjate que las líneas de comentarios contiguas se unen, mientras que las líneas en blanco y las que no comienzan con el prefijo especificado se conservan.

lunes, 5 de septiembre de 2016

fold - Limita cada línea a una longitud especificada

Folding (plegado) es el proceso de cortar líneas de texto a una anchura especificada. Como nuestros otros comandos, fold acepta tanto uno o más archivos de texto como entrada estándar. Si mandamos a fold una secuencia de texto simple, podemos ver cómo funciona:

[me@linuxbox ~]$ echo "The quick brown fox jumped over the lazy dog." | fold -w 12
The quick br
own fox jump
ed over the
lazy dog.

Aquí vemos a fold en acción. El texto enviado por el comando echo se divide en segmentos especificados por la opción -w. En este ejemplo, especificamos una anchura de línea de 12 caracteres. Si no se especifica el ancho, la opción por defecto es 80 caracteres. Fíjate cómo las líneas se cortan independientemente de los límites de las palabras. Añadir la opción -s hace que fold corte la línea en el último espacio en blanco existente antes de que se alcance el ancho de la línea:

[me@linuxbox ~]$ echo "The quick brown fox jumped over the lazy dog." | fold -w 12 -s
The quick
brown fox
jumped over
the lazy
dog.

viernes, 2 de septiembre de 2016

nl - Numera líneas

El programa nl es una herramienta más bien arcana que se usa para realizar una tarea simple. Numera las líneas. En su uso más simple, se parece a cat -n:

[me@linuxbox ~]$ nl distros.txt | head
 1 SUSE   10.2 12/07/2006
 2 Fedora 10   11/25/2008
 3 SUSE   11.0 06/19/2008
 4 Ubuntu 8.04 04/24/2008
 5 Fedora 8    11/08/2007
 6 SUSE   10.3 10/04/2007
 7 Ubuntu 6.10 10/26/2006
 8 Fedora 7    05/31/2007
 9 Ubuntu 7.10 10/18/2007
10 Ubuntu 7.04 04/19/2007

Como cat, nl puede aceptar tanto múltiples archivos como argumentos de línea de comandos, o entrada estándar. Sin embargo, nl tiene varias opciones y soporta una forma primitiva de etiquetas para permitir tipos de numeración más complejos.

nl soporta un concepto llamado "páginas lógicas" cuando numera. Esto permite a nl resetear (empezar de nuevo) la secuencia numérica cuando está numerando. Usando opciones, es posible establecer el número inicial a un valor específico y, en cierta medida, su formato. Una página lógica está dividida en encabezado, cuerpo y pie de página. Dentro de cada una de estas secciones, el numerado de líneas puede ser reseteado y/o asignarle un estilo diferente. Si le damos a nl múltiples archivos, los trata como una sola secuencia de texto. Las secciones en la secuencia de texto se indican con la presencia de algún tipo de etiqueta, bastante extraña, añadida al texto:

Tabla 21-1: Etiquetas nl
Etiqueta Significado
\:\:\: Comienzo del encabezado de la página lógica
\:\: Comienzo del cuerpo de la página lógica
\: Comienzo del pie de página de la página lógica

Cada etiqueta anterior debe aparecer sola en su propia línea. Tras procesar una etiqueta, nl la borra de la cadena de texto.

Aquí tenemos las opciones comunes de nl:

Tabla 21-2: Opciones comunes de nl
Opción Significado
-b style Establece la numeración del cuerpo a style, donde style es uno de los siguientes:
a = numera todas las líneas
t = numera sólo las líneas que no están en blanco. Es la opción por defecto.
n = ninguna línea.
pregexp = numera sólo las líneas que coinciden con la expresión regular básica regexp.
-f style Establece la numeración del pie a style. La opción por defecto es n (ninguna).
-h style Establece la numeración del encabezado a style. La opción por defecto es n (ninguna).
-i number Establece el incremento de numeración por página a number. La opción por defecto es uno.
-n format Establece el formato de numeración a format, donde format es:
ln = justificado a la izquierda, sin ceros delante.
rn = justificado a la derecha, sin ceros delante. Es la opción por defecto.
rz = justificado a la derecha, con ceros delante.
-p No resetea la numeración de páginas al principio de cada página lógica.
-s string Añade string al final de cada número de línea para crear un separador. La opción por defecto solamente es un carácter de tabulación.
-v number Establece el número de la primera línea de cada página lógica a number. La opción por defecto es uno.
-w width Establece la anchura del campo del número de línea a width. La opción por defecto es 6.

Admitámoslo, probablemente no querremos numerar líneas tan a menudo, pero podemos usar nl para ver cómo podemos combinar múltiples herramientas para realizar tareas más complejas. Trabajaremos sobre nuestro ejercicio del capítulo anterior para producir un informe de distribuciones Linux. Como usaremos nl, será útil incluir sus etiquetas encabezado/cuerpo/pie de página. Para hacerlo, las añadiremos al script sed del último capítulo. Usando nuestro editor de texto, cambiaremos el script de la siguiente forma y lo guardaremos como distros-nl.sed:

# sed script to produce Linux distributions report

1 i\
\\:\\:\\:\
\
Linux Distributions Report\
\
Name Ver. Released\
---- ---- --------\
\\:\\:
s/\([0-9]\{2\}\)\/\([0-9]\{2\}\)\/\([0-9]\{4\}\)$/\3-\1-\2/
$ a\
\\:\
\
End Of Report

El script ahora inserta las etiquetas de páginas lógicas de nl y añade un pie de página al final del informe. Fíjate que hemos tenido que duplicar las barras invertidas en nuestras etiquetas, porque normalmente se interpretan como un carácter de escape en sed.

A continuación, produciremos nuestro informe mejorado combinando sort, sed y nl:

[me@linuxbox ~]$ sort -k 1,1 -k 2n distros.txt | sed -f distros-nl.sed | nl

 Linux Distributions Report
   
   Name   Ver. Released
   ----   ---- --------
 1 Fedora 5    2006-03-20
 2 Fedora 6    2006-10-24
 3 Fedora 7    2007-05-31
 4 Fedora 8    2007-11-08
 5 Fedora 9    2008-05-13
 6 Fedora 10   2008-11-25
 7 SUSE   10.1 2006-05-11
 8 SUSE   10.2 2006-12-07
 9 SUSE   10.3 2007-10-04
10 SUSE   11.0 2008-06-19
11 Ubuntu 6.06 2006-06-01
12 Ubuntu 6.10 2006-10-26
13 Ubuntu 7.04 2007-04-19
14 Ubuntu 7.10 2007-10-18
15 Ubuntu 8.04 2008-04-24
16 Ubuntu 8.10 2008-10-30


   End Of Report

Nuestro informe es el resultado de nuestra tubería de comandos. Primero, ordenamos la lista por nombre de la distribución y versión (campos 1 y 2), luego procesamos el resultado con sed, añadiendo el encabezado del informe (incluyendo la etiqueta de página lógica de nl) y el pie de página. Finalmente, procesamos el resultado con nl, que, por defecto, sólo numera las líneas de la secuencia de texto que pertenezcan a la sección del cuerpo de la página lógica.

Podemos repetir el comando y experimentar con diferentes opciones de nl. Algunas interesantes son:

nl -n rz

y

nl -w 3 -s ' '