ordem inversa em um csv

5

Eu tenho um arquivo CSV como:

input.csv
1,2,3,10
4,5,6
7,8,9,12,28,30

Eu quero reverter as colunas neste arquivo, o que significa:

output.csv
10,3,2,1
6,5,4
30,28,12,9,8,7

Eu sei como fazer isso por uma contagem fixa de colunas, mas se a contagem de colunas variar, o que devo fazer?

    
por RKR 09.12.2016 / 09:09

6 respostas

9

Com perl , supondo que os campos no seu CSV não tenham vírgulas incorporadas, novas linhas, etc.:

perl -lpe '$_ = join ",", reverse split /,/' input.csv
    
por 09.12.2016 / 09:22
7

O CSV nem sempre pode ser processado simplesmente dividindo por linhas e, em seguida, vírgulas, pois os campos às vezes podem ter vírgulas ou novas linhas. Para poder incluir esses caracteres, os campos devem ser citados.

Esta é uma solução simples que você pode chamar a partir do shell que usa um analisador csv adequado:

ruby -e 'require "csv"; CSV.filter(&:reverse!)' < input.csv > output.csv

Se você não tem ruby, isso funciona com o python 2 e 3.

python -c $'import csv; import sys\nfor r in csv.reader(sys.stdin): r.reverse(); csv.writer(sys.stdout).writerow(r)' < input.csv > output.csv

Aqui está em várias linhas:

python < input.csv > output.csv -c '
import csv
import sys

for r in csv.reader(sys.stdin):
  r.reverse()
  csv.writer(sys.stdout).writerow(r)
'

Veja alguns exemplos em que isso funcionará quando as soluções com divisão simples de vírgulas não funcionarem:

input.csv

1,"2,3"

output.csv

"2,3",1

input.csv

1,"
2"

output.csv

"
2",1
    
por 09.12.2016 / 19:36
7

Você pode usar awk :

awk  'BEGIN{
  FS=OFS=","                       # set the field delimiter
}
{                                  # execute only on non empty line
  for(i=NF;i>=1;i--)               # loop through all elements
    printf "%s", $i (i==1?ORS:OFS) # print the parameter together with the comma or newline 
}' input.csv
    
por 09.12.2016 / 09:19
2
perl -l -a -F, -n -e 'print join ("," , reverse  @F)'  input.csv
    
por 09.12.2016 / 09:39
2
awk -F, '{for(i=NF;i>=1;i--)printf("%s,",$i);printf "\n"}' input.txt | sed "s/$,//"
    
por 09.12.2016 / 09:41
0

Usando o GNU datamash :

$ datamash -t',' reverse --no-strict <infile
10,3,2,1
6,5,4
30,28,12,9,8,7

de man datamash :

-t, --field-separator=X
    use X instead of TAB as field delimiter

reverse
    reverse field order in each line

--no-strict
    allow lines with varying number of fields
    
por 27.03.2018 / 09:47