Bagaimana saya bisa mengonversi data yang dibatasi tab ke data yang dibatasi koma?

8

Saya meminta daftar snapshot ec2 melalui alat baris perintah ec2 amazon:

ec2-describe-snapshots -H --hide-tags > snapshots.csv

Data terlihat seperti ini:

SnapshotId      VolumeId        StartTime   OwnerId         VolumeSize  Description
snap-00b66464   vol-b99a38d0    2012-01-05  5098939         160         my backup

Bagaimana saya bisa mencegat data sebelum mengarahkannya ke snapshots.csvdan melakukan hal-hal berikut:

  • ganti "tabs" dengan koma
  • merangkum nilai dengan kutipan
  • jika suatu nilai adalah semua angka, awali dengan nilai =sehingga excel akan memperlakukannya sebagai teks - misalnya OwnerIdharus "=5098939"(yang ini tidak perlu jika tidak dapat dilakukan inline dan sebagai gantinya akan memerlukan file skrip atau fungsi)

output yang diinginkan:

"SnapshotId","VolumeId","StartTime","OwnerId","VolumeSize","Description"
"snap-00b66464","vol-b99a38d0","2012-01-05","=5098939","=160","my backup"
cwd
sumber
Di sinilah seseorang memberitahu Anda untuk mengimpor menggunakan tab. Atau mereka akan melakukannya, jika Excel tidak retak.
Ignacio Vazquez-Abrams
Ya saya mencoba untuk membantu sedikit lebih baik karena sepertinya tidak terlalu panas. Juga memiliki file CSV yang hanya bisa dibuka daripada harus menggunakan perintah menu impor selalu bagus. Saya sudah mencoba mengubah ekstensi menjadi ".tsv" tanpa hasil.
cwd
Saya pikir output yang Anda inginkan agak mati. Anda memiliki banyak bidang kosong di sana (tanda kutip kosong).
Patrick

Jawaban:

10
#!/usr/bin/awk -f

BEGIN { FS = "\t"; OFS = "," }
{
    for(i = 1; i <= NF; i++) {
        if ($i + 0 == $i) { $i = "=" $i }
        else gsub(/"/, "\"\"", $i);
        $i = "\"" $i "\""
    }
    print
}

Dengan asumsi Anda memberi nama ini convert.awk, Anda dapat memanggil salah satu dari keduanya

ec2-describe-snapshots -H --hide-tags | awk -f convert.awk > snapshots.csv

atau (setelah menambahkan izin eksekusi, chmod a+x convert.awk)

ec2-describe-snapshots -H --hide-tags | ./convert.awk > snapshots.csv

Ini akan membuat kolom baru untuk setiap tab, yang akan menjaga kolom komentar bersama (kecuali jika mengandung tab), tetapi menambahkan kolom kosong (meskipun itu adalah bagaimana hasil sampel Anda terlihat, jadi mungkin Anda benar-benar menginginkannya). Jika Anda ingin membagi di semua spasi putih (ini akan menciutkan tab tambahan dalam tabel tetapi menempatkan setiap kata dalam deskripsi sebagai kolom baru), keluarkan FS="\t";pernyataan.

Untuk generasi mendatang, jika Anda tidak memerlukan spasi "s atau =s atau embedded, Anda dapat menjadikannya one-liner:

awk -v OFS=, '{$1=$1;print}'
Kevin
sumber
Solusi bersih yang bagus. Kupikir itu akan menjadi jauh lebih buruk dari itu, tapi kemudian aku bukan orang yang canggung :-)
Patrick
jadi apakah saya menyimpan ini ke dalam file seperti ./convert.sh, chmod + x, dan kemudian pipa input ke dalamnya sehingga akan mencetak output? Saya mendapatkan kesalahan: /usr/bin/awk: syntax error at source line 1 context is >>> . <<< /convert.sh.
cwd
@ cwd Anda dapat menyimpannya dalam file, saya sarankan convert.awkuntuk menunjukkan itu awkskrip dan bukan skrip bash. Saya memperbarui posting dengan baris perintah penuh, dan perhatikan bahwa saya menambahkan -fflag yang saya lupa ke baris pertama (yang memberitahukannya untuk mengartikan file sebagai perintah).
Kevin
Versi satu-baris memperlakukan setiap spasi putih sebagai pemisah bidang, bukan hanya tab. Membutuhkan -F '\ t' sebelum -V.
Paul_Pedant
4

Inilah solusi perl. Ini mungkin dilakukan dengan sed / awk, tetapi pengujian untuk bagian numerik kemungkinan akan membuatnya sangat jelek.

ec2-describe-snapshots -H --hide-tags | \
perl -e 'use Scalar::Util qw(looks_like_number);
         while (chomp($line = <STDIN>)) {
             print(join(",", map { "\"" . (looks_like_number($_) ? "=$_" :
                                           do {s/"/""/g; $_}) . "\"" }
             split(/\t/, $line)) . "\n");
         }' \
> snapshots.csv
Patrick
sumber
3

Jika Anda hanya malas seperti saya dan ingin melakukan semuanya pada satu baris perintah tanpa menulis skrip, inilah cara saya melakukannya.

ec2-describe-snapshots -H --hide-tags | sed -e 's/^I/","/g' | sed -e 's/^/"/' | sed -e 's/$/"/'> snapshots.csv

Ini ^Idibuat dengan menekan ctrl+ v i.

Pertama sedswap semua tabsuntuk ",". Yang kedua sedmenyisipkan a "di awal setiap baris, dan sed terakhir menyisipkan penutupan "di akhir setiap baris.

Tim Kennedy
sumber
Bagaimana Anda membuat ctrl + vi muncul seperti itu?
Burhan Khalid
@burhan Sintaksnya adalah <kbd>text</kbd>.
jw013
3
Atau dalam satu baris: sed -e 's/^I/","/g' -e 's/.*/"&"/'atau bahkan lebih pendek sed -e 's/^I/","/g;s/.*/"&"/'.
Arcege
3

Solusi Perl lainnya:

#!/usr/bin/perl -wln
use strict;

my($n,$s);chomp();
for $s ( split(/\t/,$_) )
{
    $s = '='.$s if ($s =~ /^\d+$/);
    $n.= '"'.$s.'",';
}
$n =~ s/(.*),/$1/;print $n;

meminta dengan ec2-describe-snapshots -H --hide-tags | /var/tmp/script.pl > output.txt

Jim
sumber
Scalar :: Util bukan modul luar, ia dilengkapi dengan perl standar.
Patrick
Benar. Permintaan maaf untuk kata-kata buruk yang saya maksudkan komentar. Terima kasih atas koreksinya.
Jim
1

sed adalah utilitas linux paling berguna yang pernah saya temui.

sed 's/\t/","/g' TabSeparatedValues.txt > CommaSeparatedValues.csv
sed -i 's/.*/"&"/' CommaSeparatedValues.csv

Perintah pertama menggantikan semua tab di setiap baris dengan koma dan tanda kutip. Perintah kedua menyisipkan tanda kutip di awal dan akhir setiap baris, sehingga setiap nilai akan dikelilingi dalam tanda kutip, yang memungkinkan koma menjadi bagian dari nilai.

Paul
sumber
0

Ini mungkin bekerja untuk Anda:

sed 's/\t\+/,/g;s/^\|$/"/g;s/,/"&"/g;s/"\([0-9]\+\)"/"=\1"/g' file
potong
sumber