¿Cómo puedo imprimir ciertos campos de una línea?

publicado por: Anonymous

Tengo un archivo de este estilo:

primerparametro; segundoparametro; 6 para0r; 
primerparametro; segundoparametro; 3 para0e; 
primerparametro; segundoparametro; 6 para0r;
primerparametro; segundoparametro; 4 para0f;
primerparametro; segundoparametro; 6 para0h; 
primerparametro; segundoparametro; 2 para0j;
primerparametro; segundoparametro; 1 para04;

Los parámetros están separados por “;”. Quiero imprimir el primer y el último parámetro con grep, para que me dé algo así como:

primerparametro; 6 para0r; 
primerparametro; 3 para0e; 
...

La orden de búsqueda sería algo así:

grep -Eio '[a-z0-9._-]*+; | [0-9]+[ ]+para+[a-z0-9]{2}+;' archivo.txt;

Sin embargo, lo que yo no quiero es que aparezca el segundo parámetro en los resultados.

solución

Existen diversas maneras de llevar a cabo tu tarea dependiendo de qué harás con cada uno de los registros obtenidos.

awk

El procesador de texto awk te permite configurar FS (field separator, o separador de campos) y OFS (output field separator, separador de campos de salida) para obtener los campos de cada línea y mostrarlos:

awk 'BEGIN {FS=OFS=";"} {print $1,$3}' archivo.txt

BEGIN te permite definir un bloque de código que se ejecutará al comienzo. En este caso es asignar como separador de campo de entrada y de salida el carácter ; ({FS=OFS=";"}).

El segundo bloque ({print $1, $3}) se ejecuta por cada línea de datos y muestra los campos 1 y 3 separados por el separador de salida OFS (;).

Nota: esta es la misma solución propuesta por fedorqui en esta otra respuesta.

cut

No se necesita un procesador pesado como awk para realizar la tarea, una sencilla solución es la que te propuse en los comentarios, usando cut de la siguiente manera:

cut -d ';' -f 1,3 archivo.txt

La herramienta cut te permite mostrar los campos que desees con el parámetro -f (en este caso, primer y tercer parámetro) y usar el delimitador que prefieras (en este caso ;, entrecomillado para que no lo considere final de instrucción).

read

También se puede usar la función interna read que permite leer datos de la corriente de entrada y separarlos por su IFS:

while IFS=";" read -r a b c ; do echo "$a;$c" ; done < archivo.txt

El bucle while se ejecutará mientras siga recibiendo datos la función read línea a línea desde el archivo archivo.txt, asignando los valores a las variables a, b y c separando la línea haciendo uso del separador configurado en IFS, mostrando únicamente los campos a y c (primero y tercero) en la salida separados por un punto y coma en el echo.

sed

La herramienta sed es muy compleja, pero tiene usos bastante sencillos como el siguiente:

sed -r 's/^([^;]*;)[^;]*;/1/' archivo.txt

Uso el modificador s para sustituir los patrones encontrados de la siguiente manera:

  • ^: empezamos desde el comienzo de cada línea.
  • ([^;]*;): primer bloque (1), desde el comienzo de línea coincide con todo lo que no sea un punto y coma (^;) e incluye en el bloque el punto y coma encontrado.
  • [^;]*;: segunda parte de la búsqueda que no será almacenada como bloque y que será descartada (no se usará en la sustitución, por lo tanto se eliminará). Cualquier carácter hasta el próximo (segundo) punto y coma.
  • 1: Sustituye los dos bloques anteriores por sólo el primero de ellos. El resto de la línea (tercer y demás parámetros) se mantendrán intactos.

Rendimiento

Comparación del rendimiento:

$ for i in $(seq 1 1000000) ; do echo "primer parametro; segundo parametro; num $i" >> archivo.txt ; done

$ time awk 'BEGIN {FS=OFS=";"} {print $1,$3}' archivo.txt | tail -n 3
primer parametro; num 999998
primer parametro; num 999999
primer parametro; num 1000000

real    0m1.439s
user    0m1.308s
sys 0m0.120s

$ time cut -d ';' -f 1,3 archivo.txt | tail -n 3
primer parametro; num 999998
primer parametro; num 999999
primer parametro; num 1000000

real    0m0.217s
user    0m0.148s
sys 0m0.084s

$ time ( while IFS=";" read -r a b c ; do echo "$a;$c" ; done < archivo.txt ) | tail -n 3
primer parametro; num 999998
primer parametro; num 999999
primer parametro; num 1000000

real    0m27.135s
user    0m25.200s
sys 0m4.268s

$ time sed -r 's/^([^;]*;)[^;]*;/1/' archivo.txt | tail -n 3
primer parametro; num 999998
primer parametro; num 999999
primer parametro; num 1000000

real    0m6.354s
user    0m6.384s
sys 0m0.152s

El ganador en este ejemplo es, por clara ventaja, la herramienta cut.

Respondido por: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *