Tengo un archivo de texto como este.
foo bar baz
1 a alpha
2 b beta
3 c gamma
Puedo usar awk para imprimir ciertas columnas, como 1 y 3, con {print $1, $3}
, pero quiero especificar las columnas a imprimir especificando el encabezado de la columna, algo así como {print $foo, $baz}
. Esto es útil para no tener que abrir el archivo y contar las columnas manualmente para ver cuál es cuál, y no tengo que actualizar el script si el número de columna o el orden cambian. ¿Puedo hacer esto con awk (u otra herramienta de shell)?
Respuesta1
awk '
NR==1 {
for (i=1; i<=NF; i++) {
f[$i] = i
}
}
{ print $(f["foo"]), $(f["baz"]) }
' file
foo baz
1 alpha
2 beta
3 gamma
Ése es un modismo inmensamente útil. Tengo muchos datos en hojas de cálculo y diferentes hojas de cálculo pueden tener un subconjunto común de columnas que me interesan, pero no necesariamente en el mismo orden en todas las hojas de cálculo o con el mismo número de otras columnas antes o entre ellas, para poder exportar. guardarlos como CSV o similar y luego simplemente ejecutar un script awk usando los nombres de las columnas en lugar de los números de las columnas es absolutamente invaluable.
Respuesta2
Lo solicitas awk
, pero también podrías utilizar una herramienta más especializada para esto: csvtool
.
csvtool -t ' ' -u ' ' namedcol foo,baz file
o
csvtool -t ' ' -u ' ' col 1,3 file
Respuesta3
Suponiendo que el archivo es un archivo TSV ("valores separados por tabulaciones"), usecsvkit
:
$ csvcut -t -c foo,baz file.tsv
foo,baz
1,alpha
2,beta
3,gamma
La salida tendrá el formato CSV adecuado, pero se puede volver a cambiar fácilmente a TSV:
$ csvcut -t -c foo,baz file.tsv | csvformat -T
foo baz
1 alpha
2 beta
3 gamma
La -c
opción de csvcut
también puede tomar números y rangos, y también puede usarse parareorganizarlas columnas de los datos de entrada (una característica que a menudo extraño en la cut
utilidad estándar).