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
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.
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
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
}
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,
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,