タブ区切りデータをコンマ区切りデータに変換するにはどうすればよいですか?


8

アマゾンのec2コマンドラインツールを介してec2スナップショットのリストをリクエストしています。

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

データは次のようになります。

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

リダイレクトする前にデータを傍受snapshots.csvし、次のことを行うにはどうすればよいですか。

  • 「タブ」をコンマに置き換えます
  • 引用符で値をカプセル化する
  • 値がすべて数値の場合は、プレフィックスとしてを付けて、=Excelでテキストとして扱われるようにします。たとえばOwnerId"=5098939"にする必要があります(これはインラインで実行できず、代わりにスクリプトファイルまたは関数が必要な場合は必要ありません)。

望ましい出力:

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

ここで、タブを使用してインポートするように指示されます。あるいは、Excelが機能していなかったとしても。
Ignacio Vazquez-Abrams

ええ、それはそれだけでそれほど熱くなっているようには見えないので、少しだけ上手くいくように手助けしようとしています。また、インポートメニューコマンドを使用する代わりに、単に開くことができるCSVファイルを用意しておくと、常に便利です。拡張子を ".tsv"に変更してみましたが、うまくいきませんでした。
cwd 2012年

私はあなたの望ましい出力が少しずれていると思います。そこには空のフィールド(空の引用符)がたくさんあります。
Patrick、

回答:


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
}

これconvert.awkに名前を付けたとすると、どちらかで呼び出すことができます

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

または(実行権限を追加した後chmod a+x convert.awk

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

これにより、タブごとに新しい列が作成され、タブが含まれていない場合はコメント列がまとめられますが、空の列が追加されます(ただし、サンプル出力はこのように表示されるため、実際に必要な場合があります)。すべての空白で分割する場合(これにより、テーブル内の余分なタブが折りたたまれますが、説明内の各単語が新しい列として配置されます)、FS="\t";ステートメントを削除します。

将来の世代では、"s、=s、または埋め込み空白が必要ない場合は、1行にすることができます。

awk -v OFS=, '{$1=$1;print}'

きれいな解決策。それはそれよりかなり醜いことになるだろうと思ったが、それから私はawkの人ではない:-)
Patrick

これを./convert.shchmod + x などのファイルに保存してから、入力をそこにパイプして出力を出力しますか?エラーが発生します:/usr/bin/awk: syntax error at source line 1 context is >>> . <<< /convert.sh
cwd 2012年

@cwdファイルに保存できます。スクリプトではなくスクリプトconvert.awkであることを示すことをお勧めします。完全なコマンドラインで投稿を更新し、最初の行に忘れていたフラグを追加したことに注意してください(ファイルをコマンドとして解釈するように指示します)。awkbash-f
Kevin

ワンライナーバージョンは、タブだけでなく、空白をフィールドセパレータとして扱います。-Vの前に-F '\ t'が必要です。
Paul_Pedant

4

これがperlソリューションです。これはsed / awkで可能かもしれませんが、数値部分をテストするとかなり醜くなります。

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

3

私のように怠惰で、スクリプトを記述せずに1つのコマンドラインですべてを実行したい場合は、次のようにします。

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

^I押すことによって作られるctrl+をv i

最初のものsedtabs、すべてのforを交換し","ます。2番目は各行の先頭にseda "を挿入し、最後のsed "は各行の最後にクロージングを挿入します。


ctrl + viをどのように表示したのですか?
Burhan Khalid、2012年

@burhan構文は<kbd>text</kbd>です。
jw013、2012年

3
または1行で:sed -e 's/^I/","/g' -e 's/.*/"&"/'またはさらに短いsed -e 's/^I/","/g;s/.*/"&"/'
Arcege 2012年

3

別のPerlソリューション:

#!/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;

で呼び出す ec2-describe-snapshots -H --hide-tags | /var/tmp/script.pl > output.txt


Scalar :: Utilは外部モジュールではなく、標準のperlが付属しています。
Patrick

そうだね。意図したコメントの不適切な表現についての謝罪。訂正ありがとうございます。
ジム・

1

sedは、私が今まで出会った中で最も有用なLinuxユーティリティです。

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

最初のコマンドは、すべての行のすべてのタブをコンマと引用符で置き換えます。2番目のコマンドは、各行の最初と最後に引用符を挿入し、各値が引用符で囲まれるようにします。これにより、コンマを値の一部にすることができます。


0

これはあなたのために働くかもしれません:

sed 's/\t\+/,/g;s/^\|$/"/g;s/,/"&"/g;s/"\([0-9]\+\)"/"=\1"/g' file
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.