Reestruturar o arquivo csv

1

Aqui está um exemplo dos dados que gostaria de modificar:

John,,
bim,bam,boom
tim,tam,toom
lam,loom,lim
Mary,,
pam,pim,poom
dam,dim,doom*

Eu tento conseguir isso:

John,bim,bam,boom
John,tim,tam,toom
John,lam,loom,lim
Mary,pam,pim,poom
Mary,dam,dim,doom

Quando um nome está sozinho em uma linha, ele se torna uma nova coluna em todas as linhas abaixo até o próximo nome ocorrer com o mesmo padrão.

Gostaria de saber se o awk ou outra ferramenta poderia ajudar, mas estou um pouco perdido.

Eu tento fazer uma condição (se as colunas 2 e 3 estiverem vazias, faça alguma coisa), mas isso parece um pouco complicado para mim agora.

    
por Plouf 07.02.2017 / 14:53

2 respostas

5

Você está pensando nas linhas certas:

I try to make a condition (if columns 2 and 3 are empty, do something)

Especificamente,

  • se as colunas 2 e 3 estiverem vazias, salve o valor da coluna 1 e continue
  • caso contrário, coloque o valor salvo na linha e imprima-o (existem várias maneiras de fazer isso)%

Então, por exemplo

awk -F, '$2=="" && $3=="" {pfx=$1; next} {print pfx "," $0}' file.csv

ou mais usando a variável separadora de campo awk

awk -F, '$2=="" && $3=="" {pfx=$1; next} {$0 = pfx FS $0; print}' file.csv

ou (como a ação padrão - quando uma regra avalia true ou FS - é imprimir o registro)

awk -F, '$2=="" && $3=="" {pfx=$1; next} {$0 = pfx FS $0} 1' file.csv
John,bim,bam,boom
John,tim,tam,toom
John,lam,loom,lim
Mary,pam,pim,poom
Mary,dam,dim,doom
    
por 07.02.2017 / 15:35
2

Alternativa Perl:

$ perl -F',' -lane 'if(@F == 1){$prefix = sprintf("%s,",@F);next;};print $prefix . $_' input.csv
John,bim,bam,boom
John,tim,tam,toom
John,lam,loom,lim
Mary,pam,pim,poom
Mary,dam,dim,doom

Isso opera na premissa de que cada linha é dividida em uma matriz de elementos usando o operador , as, e se houver apenas um item nessa matriz, usamos essa linha como prefixo e vamos para a próxima linha. Outras linhas com mais de um elemento receberão o prefixo anexado a elas. Naturalmente, o prefixo muda se e somente se a matriz tiver comprimento 1.

Ou mais curto, usando shift como sugerido por Glenn Jackman:

$ perl -F',' -lane 'if(@F == 1){$prefix = shift @F;next;};print $prefix . "," . $_' input.csv       

Ou

$ perl -F, -lane '$,=","; if (1 == @F) {$name = shift @F} else {print $name, @F}' input.csv
    
por 07.02.2017 / 19:19