Tengo el siguiente archivo:
id name age
1 ed 50
2 joe 70
Quiero imprimir solo las columnas idy 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?

catno es necesario, por cierto. Podrías usarawk '{ print $1, $3 }' file.tsvidlugar de$1y enagelugar de$3Respuestas:
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
-vcambio para obtener la variable definida en elBEGINbloque).fuente
awk -f t.awk col1 col2 ... coln inputsería idealawk -f t.awk cols=col1,col2,...,coln inputfuncionaría tambiénfor (i in out)no tiene un orden inherente.gawkofertasPROCINFO["sorted_in"]como solución, iterar sobre el índice con afor( ; ; )probablemente sea mejor.Simplemente lanzando una solución Perl al lote:
fuente
csvkitConvierta los datos de entrada a un formato csv y use una herramienta csv como
csvcutla decsvkit:Instale csvkit:
Úselo
trcon su opción de compresión-spara convertirlo en un archivo csv válido y apliquecsvcut:Si desea volver al formato de datos anterior, puede usar
tr ',' ' ' | column -tNotas
csvkit también admite diferentes delimitadores ( opción compartida
-do--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
csvformatpueden usarse para recuperar el archivo tsv:Por lo que he comprobado, solo se permite una sola pestaña.
csvlookpuede 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 dicecvscutque use pestañas como delimitador de campo. Y-do--delimiterusar cualquier carácter como delimitador.-dy-testá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, comoawklas 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.tsvycat 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,nameyage, no cambia el hecho de que el pedido sea modificable en sureadlí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+0wPor 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 agesalida
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
readse 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 100genera, el segundo obtiene el 2, el tercero obtiene el 3 y así sucesivamente. El exceso deseqsalida 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
awkscript es una cadena entre comillas dobles, que permite que las variables de shell definidas porreadsean sustituidas en el script comoawknú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.csvestá 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é
hgreppara encabezado grep , se puede usar así:El script completo es un poco más largo, porque se usa
argparsepara 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