Extraer datos de un archivo y colocarlos en diferentes archivos en función del valor de una columna

14

Generaremos un archivo csv con los siguientes valores

yp1234,577,1,3
yp5678,577,3,5
yp9012,132,8,9

Necesito extraer datos y crear archivos basados ​​en la segunda columna. Si es 577, entonces toda la línea debe extraerse y colocarse en un archivo separado. Quiero decir que necesito un archivo que tenga líneas con la segunda columna como 577 solo y otro archivo con la segunda columna como 132 solo

Intenté usar IF pero no funcionó

usuario3116123
fuente
55
En realidad, publicar el código que no funciona siempre es una buena idea.
Ricitos

Respuestas:

27

Uso awk:

awk -F, '{ print > $2 ".csv" }' file.csv

Esto creará los dos archivos 577.csvy 132.csven su directorio actual.

El comando anterior supone que solo puede tener 132o 577como el segundo campo. Creará un nombre de archivo para cada uno de los valores encontrados en el segundo campo del conjunto file.csv.

Si hay otros valores aparte de los dos que le interesan, y desea ignorar esas líneas, haga esto en su lugar:

awk -F, '$2 == "577" || $2 == "132" { print > $2 ".csv" }' file.csv
terdon
fuente
1
Hay awkimplementaciones con errores que no se pueden usar print > $2 ".cvs". En aquellos, que tendría que primero compute el nombre del archivo, y luego hacer la print: fname = $2 ".cvs"; print > fname.
Kusalananda
3

Me gusta la awksolución de terdon , pero en aras de la exhaustividad, aquí hay una sugerencia utilizando solobash

while IFS=, read -r a1 a2 a3 a4; do 
    echo "$a1,$a2,$a3,$a4" >> "$a2".csv
done < file.csv

Producirá archivos 577.csvy 132.csven el directorio actual.

grebneke
fuente
3

Para extraer todos los 577 a stdout

grep -e '^.*,577,.*,.*$' youfile.csv >result_extract_557.csv

- edit 1 Corregido, basado en el comentario de @terdon a continuación para evitar coincidencias falsas cuando al menos 3 comas en línea con 577.

grep -e '^[:alnum:]*,577,[:digit:]*,[:digit:]*$' youfile.csv >result_extract_557.csv

Pero creo que su awksolución es más integral.

X Tian
fuente
Eso coincidirá incluso si 577 está en otro campo, no en el segundo o si es parte de un campo. Por ejemplo foo577baro yp9012,132,8,577.
terdon
¿Pensé que mis comas harían que dependiera de la posición del campo?
X Tian
Lo siento, di malos ejemplos, pero .*también pueden coincidir con comas para que no sepas con qué campo coinciden. Podría ser el segundo, también podría ser el 45. Mi segunda queja fue incorrecta, tienes razón en que las comas protegen de la coincidencia foo577bar.
terdon
que hacer si | se usa el carácter en lugar de,.
user3116123
recibiendo el siguiente error grep: opción ilegal - e Uso: grep -hblcnsviw patrón de archivo. . .
user3116123
1

Utilizando csvkit:

$ csvgrep -c 2 -m 577 data.csv >output.csv

Las -c 2marcas cvsgrepconsideran la segunda columna, y con ella -m 577le pedimos que coincida con la cadena 577en esa columna.

Lo siguiente se escribirá a output.csv:

yp1234,577,1,3
yp5678,577,3,5

Para hacer coincidir varias cadenas y escribir el resultado en un archivo para cada cadena:

for pattern in 577 132; do
  csvgrep -c 2 -m "$pattern" data.csv >"output-$pattern.csv"
done

Esto creará los dos archivos output-132.csvy output-577.csv.

Kusalananda
fuente