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)?

usuario1350864
fuente

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.

Ed Morton
fuente
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
pLumo
fuente
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 ).

Kusalananda
fuente