Tengo el siguiente archivo:
id name age
1 ed 50
2 joe 70
Quiero imprimir solo las columnas id
y age
. En este momento solo uso awk
:
cat file.tsv | awk '{ print $1, $3 }'
Sin embargo, esto requiere conocer los números de columna. ¿Hay alguna manera de hacerlo donde pueda usar el nombre de la columna (especificado en la primera fila), en lugar del número de columna?
cat
no es necesario, por cierto. Podrías usarawk '{ print $1, $3 }' file.tsv
id
lugar de$1
y enage
lugar de$3
Respuestas:
Tal vez algo como esto:
Si desea especificar las columnas para imprimir en la línea de comando, puede hacer algo como esto:
(Tenga en cuenta el
-v
cambio para obtener la variable definida en elBEGIN
bloque).fuente
awk -f t.awk col1 col2 ... coln input
sería idealawk -f t.awk cols=col1,col2,...,coln input
funcionaría tambiénfor (i in out)
no tiene un orden inherente.gawk
ofertasPROCINFO["sorted_in"]
como solución, iterar sobre el índice con afor( ; ; )
probablemente sea mejor.Simplemente lanzando una solución Perl al lote:
fuente
csvkit
Convierta los datos de entrada a un formato csv y use una herramienta csv como
csvcut
la decsvkit
:Instale csvkit:
Úselo
tr
con su opción de compresión-s
para convertirlo en un archivo csv válido y apliquecsvcut
:Si desea volver al formato de datos anterior, puede usar
tr ',' ' ' | column -t
Notas
csvkit también admite diferentes delimitadores ( opción compartida
-d
o--delimiter
), pero devuelve un archivo csv:Si el archivo usa solo espacios para separar columnas (sin pestañas), los siguientes trabajos
Si el archivo usa una pestaña para separar las columnas, los siguientes trabajos
csvformat
pueden usarse para recuperar el archivo tsv:Por lo que he comprobado, solo se permite una sola pestaña.
csvlook
puede formatear la tabla en un formato de tabla de rebajasUUOC (Useless Use Of Cat) : me gusta de esta manera construir el comando.
fuente
tr
, también. Los archivos TSV son compatibles directamente, sin necesidad de convertirlos a CSV. La opción-t
(aka--tabs
) le dicecvscut
que use pestañas como delimitador de campo. Y-d
o--delimiter
usar cualquier carácter como delimitador.-d
y-t
están semi rotas. funcionan para especificar el delimitador de entrada, pero el delimitador de salida está codificado para ser siempre una coma. IMO que está roto: debe ser el mismo que el delimitador de entrada o tener otra opción para permitir que el usuario establezca el delimitador de salida, comoawk
las variables FS y OFS.Si solo quiere referirse a esos campos por sus nombres en lugar de números, puede usarread
:EDITAR
¡Por fin vi tu significado! Aquí hay una función bash que imprimirá solo las columnas que especifique en la línea de comando (por nombre ).
Así es como puede usarlo con el archivo que ha presentado:
(La función lee
stdin
.< file.tsv printColumns ...
Es equivalente aprintColumns ... < file.tsv
ycat file.tsv | printColumns ...
)Nota: ¡preste atención a los nombres de las columnas que solicita! Esta versión carece de controles de cordura, por lo que pueden suceder cosas desagradables si uno de los argumentos es algo así como
"anything; rm /my/precious/file"
fuente
id
,name
yage
, no cambia el hecho de que el pedido sea modificable en suread
línea.time { command(s); }
)time cat temp.txt | ./col1 CHR POS > /dev/null 99.144u 38.966s 2:19.27 99.1% 0+0k 0+0io 0pf+0w time awk -f col2 c1=CHR c2=POS temp.txt > /dev/null 0.294u 0.127s 0:00.50 82.0% 0+0k 0+0io 0pf+0w
Por lo que vale. Esto puede manejar cualquier número de columnas en la fuente, y cualquier número de columnas para imprimir, en cualquier secuencia de salida que elija; solo reorganiza los args ...
p.ej. llamada:
script-name id age
salida
fuente
Si el archivo que está leyendo nunca podría ser generado por el usuario, podría abusar de la lectura incorporada:
La primera línea completa del archivo de entrada se sustituye en la lista de argumentos, por lo que
read
se pasan todos los nombres de campo de la línea de encabezado como nombres de variables. Al primero de ellos se le asigna el 1 queseq 100
genera, el segundo obtiene el 2, el tercero obtiene el 3 y así sucesivamente. El exceso deseq
salida es absorbido por la variable ficticiaextra
. Si conoce la cantidad de columnas de entrada con anticipación, puede cambiar las 100 para que coincidan y deshacerse de ellasextra
.El
awk
script es una cadena entre comillas dobles, que permite que las variables de shell definidas porread
sean sustituidas en el script comoawk
números de campo.fuente
Por lo general, es más fácil solo mirar el encabezado del archivo, contar el número de la columna que necesita ( c ) y luego usar Unix
cut
:Pero cuando hay muchas columnas o muchos archivos, uso el siguiente truco feo:
Probado en OSX,
file.csv
está delimitado por comas.fuente
Aquí hay una forma rápida de seleccionar una sola columna.
Digamos que queremos la columna llamada "foo":
Básicamente, tome la línea de encabezado, divídala en varias líneas con un nombre de columna por línea, numere las líneas, seleccione la línea con el nombre deseado y recupere el número de línea asociado; luego use ese número de línea como el número de columna para el comando de corte.
fuente
Buscando una solución similar (necesito la columna llamada id, que podría tener un número de columna variable), me encontré con esta:
fuente
Escribí un script de Python para este propósito que básicamente funciona así:
Lo llamé
hgrep
para encabezado grep , se puede usar así:El script completo es un poco más largo, porque se usa
argparse
para analizar argumentos de línea de comando y el código es el siguiente:fuente
awk
, a pesar de toda su antigüedad, está intrínsecamente indexado con enteros, como escut
.Aquí hay varias herramientas diseñadas para manejar datos indexados por nombre (la mayoría de ellos manejan solo CSV y TSV, que son formatos de archivo muy populares):
fuente
Pruebe esta pequeña utilidad awk para cortar encabezados específicos: https://github.com/rohitprajapati/toyeca-cutter
Ejemplo de uso -
fuente