print - awk unix
Extrae columnas específicas del archivo delimitado usando Awk (8)
Lo siento si esto es demasiado básico. Tengo un archivo csv donde las columnas tienen una fila de encabezado (v1, v2, etc.). Entiendo que para extraer las columnas 1 y 2, tengo que hacer lo siguiente: awk -F "," ''{print $1 "," $2}'' infile.csv > outfile.csv
. Pero, ¿qué pasa si tengo que extraer, por ejemplo, las columnas 1 a 10, 20 a 25 y 30, 33? Como una adición, ¿hay alguna manera de extraer directamente con los nombres de encabezado en lugar de con los números de columna?
Como mencionó @Tom, los enfoques de corte y awk en realidad no funcionan para CSV con cadenas entre comillas. Una alternativa es un módulo para python que proporciona la herramienta de línea de comandos csvfilter. Funciona como corte, pero maneja correctamente las columnas de CSV:
csvfilter -f 1,3,5 in.csv > out.csv
Si tiene python (y debería), puede instalarlo simplemente así:
pip install csvfilter
Tenga en cuenta que la indexación de columna en csvfilter comienza con 0 (a diferencia de awk, que comienza con $ 1). Más información en https://github.com/codeinthehole/csvfilter/
No sé si es posible hacer rangos en awk. Podría hacer un ciclo for, pero tendría que agregar manejo para filtrar las columnas que no desea. Probablemente sea más fácil hacer esto:
awk -F, ''{OFS=",";print $1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$20,$21,$22,$23,$24,$25,$30,$33}'' infile.csv > outfile.csv
algo más que considerar, y esto más rápido y más conciso:
cut -d "," -f1-10,20-25,30-33 infile.csv > outfile.csv
En cuanto a la segunda parte de su pregunta, probablemente escribiría un script en Perl que sepa cómo manejar las filas del encabezado, analizar los nombres de las columnas de stdin o un archivo y luego hacer el filtrado. Probablemente sea una herramienta que me gustaría tener para otras cosas. No estoy seguro de hacerlo en un solo trazador de líneas, aunque estoy seguro de que se puede hacer.
No uso awk, pero la forma más sencilla en que pude hacer esto fue simplemente usar csvtool . También tuve otros casos de uso para usar csvtool y puede manejar las comillas o los delimitadores de manera apropiada si aparecen dentro de los datos de la columna en sí.
csvtool format ''%(2)/n'' input.csv
csvtool format ''%(2),%(3),%(4)/n'' input.csv
Reemplazar 2 con el número de columna extraerá efectivamente los datos de columna que está buscando.
Otros han respondido a su pregunta anterior. Para esto:
Como una adición, ¿hay alguna manera de extraer directamente con los nombres de encabezado en lugar de con los números de columna?
No lo he probado, pero puedes guardar el índice de cada encabezado en un hash y luego usar ese hash para obtener su índice más adelante.
for(i=0;i<$NF;i++){
hash[$i] = i;
}
Luego, úsala:
j = hash["header1"];
print $j;
Otros idiomas tienen atajos para rangos de números de campo, pero no awk, tendrás que escribir tu código como tu miedo ;-)
awk -F, ''BEGIN {OFS=","} { print $1, $2, $3, $4 ..... $30, $33}'' infile.csv > outfile.csv
No existe una función directa en awk para usar nombres de campo como especificadores de columna.
Espero que esto ayude.
Puede usar un for-loop para abordar un campo con $ i :
ls -l | awk ''{for(i=3 ; i<8 ; i++) {printf("%s/t", $i)} print ""}''
Si Perl es una opción:
perl -F, -lane ''print join ",",@F[0,1,2,3,4,5,6,7,8,9,19,20,21,22,23,24,29,32]''
-a
línea de autosplits en la @F
campos @F
. Los índices comienzan en 0 (no 1 como en awk)
-F,
separador de campo es,
Si su archivo CSV contiene comas entre comillas, los analizadores de CSV completos como Perl''s Text::CSV_XS
están diseñados para manejar ese tipo de rareza.
perl -MText::CSV_XS -lne ''BEGIN{$csv=Text::CSV_XS->new()} if($csv->parse($_)){@f=$csv->fields();print (join ",",@f[0,1,2,3,4,5,6,7,8,9,19,20,21,22,23,24,29,32])}''
Proporcioné más explicación dentro de mi respuesta aquí: análisis de archivo csv usando gawk
Tabulator es un conjunto de herramientas de línea de comandos de Unix para trabajar con archivos csv que tienen líneas de encabezado. Aquí hay un ejemplo para extraer columnas por nombre de un archivo test.csv:
name,sex,house_nr,height,shoe_size
arthur,m,42,181,11.5
berta,f,101,163,8.5
chris,m,1333,175,10
don,m,77,185,12.5
elisa,f,204,166,7
Luego tblmap -k name,height test.csv
produce
name,height
arthur,181
berta,163
chris,175
don,185
elisa,166