Bei einer Datei wie dieser
First,Last,Age
Cory,Klein,27
John Jacob,Smith,30
Gibt es ein Befehlszeilenprogramm, um den Inhalt so zu transponieren, dass die Ausgabe so aussieht?
First,Cory,John Jacob
Last,Klein,Smith
Age,27,30
Bei einer Datei wie dieser
First,Last,Age
Cory,Klein,27
John Jacob,Smith,30
Gibt es ein Befehlszeilenprogramm, um den Inhalt so zu transponieren, dass die Ausgabe so aussieht?
First,Cory,John Jacob
Last,Klein,Smith
Age,27,30
Antworten:
ruby -rcsv -e 'puts CSV.parse(STDIN).transpose.map &:to_csv' < in.csv > out.csv
CSV-Analyse ist nur mit POSIX-Tools nicht einfach durchzuführen, es sei denn, Sie verwenden eine vereinfachte CSV-Variante ohne Anführungszeichen (sodass in einem Feld keine Kommas angezeigt werden können). Selbst dann scheint es nicht einfach zu sein, diese Aufgabe mit awk oder einer anderen Textverarbeitung zu erledigen. Sie können Perl mit Text::CSV
, Python mit csv
, R mit read.csv
, Ruby mit CSV , ... verwenden. (Alle diese sind Teil der Standardbibliothek der jeweiligen Sprache mit Ausnahme von Perl.)
Zum Beispiel 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])
Von /programming//a/2776078 :
$ apt-get install csvtool
Und dann konvertieren
$ csvtool transpose input.csv > ouput.csv
Oder in der Pipeline
$ ... | csvtool transpose - | ...
... | csvtranspose | ...
würde nur die Syntax übertreffen.
Eine schnelle und schmutzige Bash- Lösung:
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
Zelle ist codiert "this ""is"" example"
Ich bin nicht überzeugt, ob diese Lösung solche Fälle ordnungsgemäß behandelt
In Anbetracht der vorgeschlagenen Einschränkung (keine Anführungszeichen, keine eingebetteten Kommas) ist es in awk einfach (wie es in Perl ohne Berücksichtigung von mehr als tausend Zeilen in wäre CSV.pm
, 2300 Zeilen in csv.rb
- Python hat nur 450 Zeilen in csv.py
).
Hier ist ein Beispiel für 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];
}
}
Übrigens: Das angegebene Beispiel hatte zusätzlichen Platz, von dem OP annahm, dass er entfernt werden würde. Die anderen Beispiele haben dieses Detail nicht angesprochen.
python
, b)ruby
ist nicht weniger portabel alspython
und c) zeigt auch, wie die Eingabe / Ausgabe übergeben wird Dateien. Bravo @luikore und willkommen bei Unix & Linux. Bitte bleiben Sie dabei.