Dado um arquivo como esse
First,Last,Age
Cory,Klein,27
John Jacob,Smith,30
Existe um utilitário de linha de comando para transpor o conteúdo para que a saída apareça assim
First,Cory,John Jacob
Last,Klein,Smith
Age,27,30
Dado um arquivo como esse
First,Last,Age
Cory,Klein,27
John Jacob,Smith,30
Existe um utilitário de linha de comando para transpor o conteúdo para que a saída apareça assim
First,Cory,John Jacob
Last,Klein,Smith
Age,27,30
Respostas:
ruby -rcsv -e 'puts CSV.parse(STDIN).transpose.map &:to_csv' < in.csv > out.csv
A análise de CSV não é feita facilmente apenas com as ferramentas POSIX, a menos que você esteja usando uma variante simplificada de CSV sem aspas (para que vírgulas não possam aparecer em um campo). Mesmo assim, essa tarefa não parece fácil de ser feita com o awk ou outro processamento de texto na ferramenta. Você pode usar Perl com Text::CSV
, Python com csv
, R com read.csv
, Ruby com CSV ,… (Tudo isso faz parte da biblioteca padrão da respectiva linguagem, exceto Perl.)
Por exemplo, em Python:
import csv, sys
rows = list(csv.reader(sys.stdin))
writer = csv.writer(sys.stdout)
for col in xrange(0, len(rows[0])):
writer.writerow([row[col] for row in rows])
$ apt-get install csvtool
E depois converter
$ csvtool transpose input.csv > ouput.csv
Ou no pipeline
$ ... | csvtool transpose - | ...
... | csvtranspose | ...
iria superar isso, em termos de sintaxe.
Uma solução rápida e suja do bash :
c=1
file=file.txt
num_lines=$(wc -l < "$file")
for ((i=0; i<num_lines; i++)) {
cut -d, -f$c "$file" | paste -sd ','
((c++))
}
for ((i=1; i<=$num_cols; ++i)); do paste -s -d, <(cut -f$i -d, file.txt); done
this "is" example
celular é codificado "this ""is"" example"
Não estou convencido se esta solução alças tais casos corretamente
Dada a limitação sugerida (sem citação, sem vírgulas incorporadas), é simples no awk (como seria em perl, não levando em conta mais de mil linhas em CSV.pm
, 2300 linhas em csv.rb
- python tem apenas 450 linhas em csv.py
).
Aqui está um exemplo para o awk:
#!/usr/bin/awk -f
BEGIN { width=0; }
{
max = split($0, list, ",");
# printf "%d:%s\n", NR, $0;
if (width < max)
width = max;
for (n = 1; n <= max; ++n) {
sub("^[ ]*","",list[n]);
sub("[ ]*$","",list[n]);
# printf "\t%d:%s\n", n, list[n];
if ( columns[n] != "" ) {
columns[n] = columns[n] ", ";
}
columns[n] = columns[n] list[n];
}
}
END {
# printf "%d columns\n", width;
for (n = 1; n <= width; ++n) {
printf "%s\n", columns[n];
}
}
A propósito: o exemplo dado tinha espaço extra que o OP assumiu que seria removido; os outros exemplos não abordaram esse detalhe.
python
, b)ruby
não é menos portátil do quepython
ec) mostra também como passar a entrada / saída arquivos. Bravo @luikore, e bem-vindo ao Unix e Linux. Por favor, fique por aqui.