Imprimir columnas en awk por nombre de encabezado


11

Tengo un archivo de texto así

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 para imprimir especificando el encabezado de la columna, algo así {print $foo, $baz}. Esto es útil para no tener que abrir el archivo y contar las columnas manualmente para ver qué columna es cuál, y no tengo que actualizar el script si cambia el número de columna o el orden. ¿Puedo hacer esto con awk (u otra herramienta de shell)?

Respuestas:


16
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

Ese es un idioma 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 / entre ellas para poder exportar ellos 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.


Esto es un gran agradecimiento y funciona para mis propósitos. ¿Eres capaz de aclarar cómo funciona esto para un principiante awk? ¿Qué está haciendo la sintaxis f [$ i] en esto y cómo funciona awk qué columnas coinciden con las cadenas?
AlexLipp

De nada. Esa es la sintaxis awk absolutamente básica, solo busque campos y matrices en la página de manual de awk (o búscalo en google). Agregue print iand print $iy print f [$ i] `declaraciones en el ciclo, etc. para rastrear qué sucede si eso ayuda.
Ed Morton

0

Usted pide awk, pero también se puede utilizar una herramienta más especializada para esto: csvtool.

csvtool -t ' ' -u ' ' namedcol foo,baz file

o

csvtool -t ' ' -u ' ' col 1,3 file

0

Suponiendo que el archivo es un archivo TSV ("valores separados por tabulaciones"), use csvkit:

$ csvcut -t -c foo,baz file.tsv
foo,baz
1,alpha
2,beta
3,gamma

La salida tendrá el formato CSV adecuado, pero podría cambiarse fácilmente a TSV:

$ csvcut -t -c foo,baz file.tsv | csvformat -T
foo     baz
1       alpha
2       beta
3       gamma

La -copción csvcuttambién puede tomar números y rangos, y también puede usarse para reorganizar las columnas de los datos de entrada (una característica que a menudo echo de menos en la cututilidad estándar ).

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.