Dato un file come questo
First,Last,Age
Cory,Klein,27
John Jacob,Smith,30
Esiste un'utilità della riga di comando per trasporre i contenuti in modo che l'output appaia così
First,Cory,John Jacob
Last,Klein,Smith
Age,27,30
Dato un file come questo
First,Last,Age
Cory,Klein,27
John Jacob,Smith,30
Esiste un'utilità della riga di comando per trasporre i contenuti in modo che l'output appaia così
First,Cory,John Jacob
Last,Klein,Smith
Age,27,30
Risposte:
ruby -rcsv -e 'puts CSV.parse(STDIN).transpose.map &:to_csv' < in.csv > out.csv
L'analisi CSV non viene eseguita facilmente solo con gli strumenti POSIX, a meno che non si stia utilizzando una variante CSV semplificata senza virgolette (quindi le virgole non possono apparire in un campo). Anche allora questo compito non sembra facile da fare con awk o altri strumenti di elaborazione del testo. Puoi usare Perl con Text::CSV
, Python con csv
, R con read.csv
, Ruby con CSV , ... (Tutti questi fanno parte della libreria standard del rispettivo linguaggio ad eccezione di Perl.)
Ad esempio, in 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 poi converti
$ csvtool transpose input.csv > ouput.csv
O in cantiere
$ ... | csvtool transpose - | ...
... | csvtranspose | ...
Avrebbe solo battuto quello, in termini di sintassi.
Una soluzione bash veloce e sporca :
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
cella è codificata "this ""is"" example"
Non sono convinto che questa soluzione gestisca correttamente questi casi
Data la limitazione suggerita (senza virgolette, senza virgole incorporate), è semplice in awk (come sarebbe in perl non tenendo conto di oltre mille righe in CSV.pm
, 2300 righe in csv.rb
- python ha solo 450 righe in csv.py
).
Ecco un esempio di 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 proposito: l'esempio dato aveva spazio extra che OP supponeva fosse rimosso; gli altri esempi non hanno affrontato questo dettaglio.
python
, b)ruby
non è meno portatile dipython
, ec) questo mostra anche come passare l'input / output File. Bravo @luikore, e benvenuto su Unix e Linux. Per favore, restate in giro.