recorta uma coluna de matriz int em um CSV sem cortar outra matriz varchar

2

Eu tenho um CSV onde parece

details.csv

1,2,3,4,5,2015-07-30 23:17:12,2015-07-30 23:39:12,103.4,104.2,1.2,"{1,2,3}",{NORMAL},1,2,
2,2,6,4,5,2015-07-30 12:17:12,2015-07-30 12:39:12,103.4,104.2,1.8,"{4,5,6,7,8,9}",{BOOKING},1,2,
3,2,3,4,9,2015-07-30 10:17:12,2015-07-30 10:39:12,103.4,104.2,1.9,"{1,9}","{NORMAL,BOOKING}",1,2,

Aqui a coluna 15 está vazia e a coluna 12 não tem aspas quando é um valor único ( {BOOKING} ) e tem aspas quando tem mais de um valor ( "{RESERVA, NORMAL}" ).

A partir disso eu queria remover o 11 a coluna que é um array int e não ter tamanho fixo.Assim, a saída será semelhante a

mod_details.csv
1,2,3,4,5,2015-07-30 23:17:12,2015-07-30 23:39:12,103.4,104.2,1.2,{NORMAL},1,2,
2,2,6,4,5,2015-07-30 12:17:12,2015-07-30 12:39:12,103.4,104.2,1.8,{BOOKING},1,2,
3,2,3,4,9,2015-07-30 10:17:12,2015-07-30 10:39:12,103.4,104.2,1.9,"{NORMAL,BOOKING}",1,2,

Então eu tentei:

sed 's/,"{.*}"//' details.csv > mod_details.csv

Mas o problema é que eu obtenho a saída como

mod_details.csv
1,2,3,4,5,2015-07-30 23:17:12,2015-07-30 23:39:12,103.4,104.2,1.2,{NORMAL},1,2,
2,2,6,4,5,2015-07-30 12:17:12,2015-07-30 12:39:12,103.4,104.2,1.8,{BOOKING},1,2,
3,2,3,4,9,2015-07-30 10:17:12,2015-07-30 10:39:12,103.4,104.2,1.9,1,2,

Onde também remove os valores da 12ª coluna que têm mais de um valor, porque também tem aspas. Qualquer ajuda é apreciada. Obrigado antecipadamente.

    
por joker21 06.12.2016 / 03:09

4 respostas

2

Na verdade, isso não é particularmente difícil. Você só precisa usar um padrão mais específico que {.*} :

sed 's/"{\([0-9],\)\+[0-9]}",//' details.csv
    
por 06.12.2016 / 11:33
0

Como um passo para encontrar uma resposta, você pode achar útil a seguinte função do shell. Eu o escrevi para ver CSVs na linha de comando em um belo layout "bonito".

Observe que exclui as aspas e cita novas linhas (e aspas duplas), o que pode não ser o que você quer, mas é útil para uma visualização rápida e ter as colunas alinhadas corretamente.

excel() {
    sed -E -e ':t' -e '/^[^"]*("[^"]*"[^"]*)*$/!{N;s/\n//;bt' -e'}' "$@" |
      awk -F\" -v OFS= 'NF>1 {for (i=2;i<=NF;i+=2) gsub(/,/, "", $i)} 1' |
      sed 's/,/,"/g' | column -ts, | tr -d '"' | less -S
}
    
por 06.12.2016 / 03:35
0

Usando csvkit :

$ csvcut -C 11 details.csv
1,2,3,4,5,2015-07-30 23:17:12,2015-07-30 23:39:12,103.4,104.2,1.2,{NORMAL},1,2,
2,2,6,4,5,2015-07-30 12:17:12,2015-07-30 12:39:12,103.4,104.2,1.8,{BOOKING},1,2,
3,2,3,4,9,2015-07-30 10:17:12,2015-07-30 10:39:12,103.4,104.2,1.9,"{NORMAL,BOOKING}",1,2,
    
por 07.02.2017 / 16:38
0

A divisão de cada linha em matriz em " como delimitador é uma abordagem muito mais fácil. Seu array int então se torna o elemento 1 do array, o qual podemos definir para uma string nula, e o próximo (element 2) terá uma vírgula extra anexada ao final, para que possamos extrair uma sub-string desse valor inicial. do segundo caractere. Agora, precisamos lidar com aspas duplas retornando para a parte {NORMAL,BOOKING} de alguma forma. Com a linha de separação em " como delimitador, isso também é feito, porque a linha terá o campo 3. No caso de outras linhas, não há mais aspas, portanto, nossa matriz de itens conterá apenas itens até o índice 2. Se houver o índice 3, sabemos que devemos citar isso.

O perl one-liner abaixo faz exatamente como descrito acima:

$ perl -F'"' -lane '$F[1]="";$F[2]=substr($F[2],1);$F[3]= "\"" . $F[3] . "\"" if $F[3];print @F' inpu>
1,2,3,4,5,2015-07-30 23:17:12,2015-07-30 23:39:12,103.4,104.2,1.2,{NORMAL},1,2,
2,2,6,4,5,2015-07-30 12:17:12,2015-07-30 12:39:12,103.4,104.2,1.8,{BOOKING},1,2,
3,2,3,4,9,2015-07-30 10:17:12,2015-07-30 10:39:12,103.4,104.2,1.9,"{NORMAL,BOOKING}",1,2,
    
por 07.02.2017 / 21:53

Tags