viernes, 3 de febrero de 2023

Flujo de datos (streams)

Posted by q3it on viernes, febrero 03, 2023 in

 
Hoy voy a hablar sobre flujos de datos "strings" en inglés. Nosotros cuando ejecutamos un comando se van a generar hasta tres flujos de datos, el primero es el llamado entrada estándar en inglés stdin, este se le asocia con el número cero, esta entrada estándar por defecto es el teclado.
 
Cuando estamos ejecutando un comando está pidiendo algún contenido para su procesamiento, esperará que nosotros escribamos algo. Aunque no lo parezca cuando nosotros estamos ejecutando el comando grep y la especificamos un filtro y como argumento un fichero, estamos cambiando el comportamiento de esta entrada, si nosotros no especificamos un fichero lo que estaría esperando es que escribiéramos en el teclado. Una vez que este comando ha hecho las operaciones necesarias pues se creará otro flujo de datos.
 
Si tiene que mostrar algo por pantalla que es la salida estándar stdout "standard output" y se asocia el número 1. Si este comando tiene que mostrar algunos errores ,por ejemplo, el comando ls y le ponemos un directorio que no existe, este va a mostrar una salida estándar de errores stderr "standard error output" y se asocia el número 2. Tanto la salida estándar, como la salida estándar de errores es la pantalla. Por eso nosotros cada vez que tenemos un comando y genere alguna salida ya sea de errores o norma, lo vamos a ver en pantalla.
 
Nosotros tenemos un fichero llamado comandos.txt.

 
Y hacemos una búsqueda de vocales, especificamos el fichero. 
 
 
Como vemos aquí al pasarle un argumento estamos cambiando el comportamiento de la entrada estándar, si nosotros no especificamos un fichero lo que nos está pidiendo es que nosotros le mandemos el texto.
 
 
Podemos por ejemplo, escribir el comando sed y la salida vemos que sigue siendo por pantalla, cuando hemos acabado de entrar nuestros datos pulsaremos las teclas Ctrl+d para que acabe correctamente, si queremos finalizarlo sin que acabe correctamente utilizaremos Ctrl+c para cancelar la ejecución del comando.
 
Vamos a ver cómo cambia el comportamiento de la salida estándar y de la salida estándar de errores. Para ello, para el flujo de datos de entrada ya hemos visto que indicándole un argumento nosotros le estábamos cambiando el comportamiento pero además podemos utilizar menor que < y el nombre del fichero.
 
Por ejemplo, con el comando tr, si nosotros queremos cambiar de minúsculas a mayúsculas veíamos que había que indicarle un rango de minúsculas y luego un rango de mayúsculas y si nosotros le pasamos como argumento un fichero nos da error. ¿Porqué? es porque en su sintaxis nosotros tenemos que dárselo como un flujo de datos, por ejemplo, cat comandos.txt luego un | tr '[a-z]' '[A-Z]' 
 
 
Entonces en este caso, también estamos cambiando el comportamiento de entrada estándar, en vez de ser el teclado lo que va a ser es lo que le hemos enviado con con el pipe |, pero si nosotros no especificamos ningún fichero vemos que lo que nos está pidiendo es que nosotros escribamos algo, por ejemplo un comando.
 
 
Pero además nosotros podemos utilizar cambiarles el comportamiento indicándole el fichero. Entonces utilizaremos el menor que < el nombre del fichero y vemos que ahora sí que funciona con < estamos cambiando el comportamiento de la entrada estándar.
 
 
Para la salida vamos a utilizar el mayor que > y el fichero donde nosotros queremos redirigió. Por ejemplo, si nosotros hacemos sort comandos.txt nos lo ordena. Nosotros podemos cambiar el comportamiento, en vez de mostrarlo por pantalla le pedimos lo nos guardemos en un fichero y ahora ya no nos lo muestra.

 
En cambio en el fichero la salida del comando sort se puede ver. Si nosotros lo ejecutamos de nuevo se va sobrescribir con el contenido que nosotros le hemos enviado desde el comando. Pero si lo que queremos es añadirlo, entonces añadiremos otro mayor que >> teniendo dos , y lo que hará es añadir al final del fichero la salida del comando sort, que ahora tenemos la salida anterior y la salida nueva.
 
 
Imaginemos que nuestro comando por algún motivo genera algún error, entonces podemos redirigir este error a un fichero, también imaginemos que nosotros hacemos un ls de nuestro directorio y de un directorio que no existe.
 
 
Vemos que primero nos muestra un error indicando que /noexisten no existe y luego nos lista el contenido del directorio actual. Si nosotros les redirigimos la salida estándar a ls.txt, vemos que en pantalla sólo se muestra el error y en cambio el contenido del fichero en ls.txt se nos mostrará la salida del comando en el directorio punto que es el directorio actual.
 
 
Si nosotros queremos redirigir los errores podemos poner un 2 > ls.txt.err y vamos a tener el error ahora redirigido a este fichero. 
 
 
Si lo que queremos es que tanto la salida estándar como la salida de errores vayan al mismo fichero. Entonces vamos a tener que utilizar esta sintaxis, la salida de errores redirigir a la salida normal, a la salida estándar. Entonces en este caso pondremos en vez de un fichero un ampersand & y el número 1 que indica el flujo de salida estándar y, ahora en nuestro fichero vamos a tener tanto la salida estándar como la salida de errores.
 

 
Y esto nosotros lo podemos también abreviar poniendo aun & mayor que > y ahora redirige tanto a la salida estándar como la salida de errores al mismo documento.
 
 
Una advertencia cuando nosotros estamos trabajando con flujos de datos no debemos utilizar el mismo documento para la entrada y para la salida, porque lo que hará es sobrescribir este documento y ponerlo en base. Entonces nuestra entrada para nuestro fichero no tendrá nada y nosotros perderemos los datos. Lo mejor es que la redirección cree un nuevo fichero.