如何将制表符分隔的数据转换为逗号分隔的数据?


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没问题,他们就会这样做。
伊格纳西奥·巴斯克斯

是的,我正在尝试帮助自己脱颖而出,因为它本身似乎并没有那么热。还有一个可以直接打开而不需要使用导入菜单命令的CSV文件总是很不错的。我已经尝试过将扩展名更改为“ .tsv”,但是没有运气。
cwd 2012年

我认为您想要的输出有点偏离。您那里有很多空字段(空引号)。
Patrick

Answers:


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或嵌入的空格,可以将其设置为单行:

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

不错的干净解决方案。以为这会比这丑陋得多,但后来我不是一个笨拙的人:-)
Patrick

那么我是否将该文件保存到./convert.shchmod + x 等文件中,然后将输入通过管道传输到该文件中,以便它将输出输出?我收到一个错误:/usr/bin/awk: syntax error at source line 1 context is >>> . <<< /convert.sh
cwd 2012年

@cwd您可以将其保存在文件中,建议您将其convert.awk表示为awk脚本而不是脚本bash。我用完整的命令行更新了帖子,并注意我-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

如果您像我一样懒惰,并且想要在一个命令行中完成所有操作而无需编写脚本,那么这就是我的操作方法。

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

^I被压制而成ctrl+ v i

第一sed互换所有tabs","。第二sed"在每行的开头插入a ,最后一个sed "在每行的末尾插入一个结尾。


您是如何让ctrl + vi像这样显示的?
Burhan Khalid 2012年

@burhan的语法是<kbd>text</kbd>
2012年

3
或一行: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

真正。不好意思表达我的意图。谢谢你的纠正。
吉姆(Jim)

1

sed是我遇到过的最有用的linux实用程序。

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

第一个命令用逗号和引号替换每一行中的所有选项卡。第二个命令在每行的开头和结尾插入引号,以便将每个值括在引号中,从而允许逗号成为值的一部分。


0

这可能对您有用:

sed 's/\t\+/,/g;s/^\|$/"/g;s/,/"&"/g;s/"\([0-9]\+\)"/"=\1"/g' file
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.