Extraia dados de um arquivo e coloque-os em arquivos diferentes, com base no valor de uma coluna

14

Vamos gerar um arquivo csv com valores abaixo

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

Preciso extrair dados e criar arquivos com base na segunda coluna. Se for 577, toda a linha deverá ser extraída e colocada em um arquivo separado. Quero dizer, preciso de um arquivo que tenha linhas com a segunda coluna apenas como 577 e outro arquivo com a segunda coluna como 132 sozinha

Eu tentei usar o IF, mas não funcionou

user3116123
fonte
5
Publicar o código que não funciona é sempre uma boa ideia.
7288 goldilocks

Respostas:

27

Use awk:

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

Isso criará os dois arquivos 577.csve 132.csvno seu diretório atual.

O comando acima pressupõe que você só pode ter 132ou 577como o segundo campo. Ele criará um nome de arquivo para cada um dos valores encontrados no segundo campo do todo file.csv.

Se houver outros valores além dos dois nos quais você estiver interessado e desejar ignorar essas linhas, faça o seguinte:

awk -F, '$2 == "577" || $2 == "132" { print > $2 ".csv" }' file.csv
terdon
fonte
1
Existem awkimplementações de buggy que não podem ser usadas print > $2 ".cvs". Sobre aqueles, você teria que primeiro compute o nome do arquivo, em seguida, fazer o print: fname = $2 ".cvs"; print > fname.
Kusalananda
3

Eu gosto da awksolução de Terdon , mas por uma questão de integridade, aqui está uma sugestão usando apenasbash

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

Ele produzirá arquivos 577.csve 132.csvno diretório atual.

Grebneke
fonte
3

Para extrair todos os 577 para stdout

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

- edit 1 Corrigido, com base no comentário de @ terdon abaixo para evitar correspondências falsas quando pelo menos 3 vírgulas estiverem alinhadas com 577.

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

Mas acho que sua awksolução é mais abrangente.

X Tian
fonte
Isso corresponderá mesmo se 577 estiver em outro campo, não no segundo ou se fizer parte de um campo. Por exemplo foo577barou yp9012,132,8,577.
terdon
Eu pensei que minhas vírgulas tornariam a posição do campo dependente?
X Tian
Desculpe, dei exemplos ruins, mas eles .*também podem corresponder vírgulas para que você não saiba qual campo está correspondendo. Poderia ser o segundo, também poderia ser o 45º. Minha segunda reclamação estava errada, você está certo ao proteger as vírgulas da correspondência foo577bar.
terdon
o que fazer se | O caractere é usado em vez de,.
user3116123
recebendo abaixo do erro grep: opção ilegal - e Uso: arquivo de padrão grep -hblcnsviw. . .
user3116123
1

Usando csvkit:

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

As -c 2marcas cvsgrepconsideram a segunda coluna e, com -m 577isso, solicitamos que ela corresponda à string 577dessa coluna.

O seguinte será escrito para output.csv:

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

Para corresponder a um número de strings e escreva a saída em um arquivo para cada string:

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

Isso criará os dois arquivos output-132.csve output-577.csv.

Kusalananda
fonte