Como posso converter dados delimitados por tabulações em dados delimitados por vírgula?

8

Estou solicitando uma lista de snapshots ec2 através da ferramenta de linha de comando ec2 da amazon:

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

Os dados parecem com algo assim:

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

Como posso interceptar os dados antes de redirecioná-los para snapshots.csv e fazer o seguinte:

  • substitua "guias" por vírgulas
  • encapsula valores com citações
  • se um valor for todos os números, prefixe-o com = para que o Excel o trate como texto - por exemplo OwnerId deve ser "=5098939 "(este não é necessário se não puder ser feito inline e exigiria um arquivo ou função de script)

resultado desejado:

"SnapshotId","VolumeId","StartTime","OwnerId","VolumeSize","Description"
"snap-00b66464","vol-b99a38d0","2012-01-05","=5098939","=160","my backup"
    
por cwd 06.01.2012 / 23:42

6 respostas

9
#!/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
}

Supondo que você nomeie esse convert.awk , você pode ligar para

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

ou (depois de adicionar permissões de execução, chmod a+x convert.awk )

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

Isso fará uma nova coluna para cada tab, que manterá a coluna de comentário unida (a menos que contenha tabulações), mas adicione colunas vazias (embora seja assim que o resultado de sua amostra parece, então talvez você realmente queira isso). Se você quiser dividir em todos os espaços em branco (isso irá recolher guias extras dentro da tabela, mas colocar cada palavra na descrição como uma nova coluna), tire a instrução FS="\t"; .

Para as gerações futuras, se você não precisa do " s ou do = s ou do espaço em branco incorporado, é possível torná-lo uma única linha:

awk -v OFS=, '{$1=$1;print}'
    
por 07.01.2012 / 00:36
4

Aqui está uma solução perl. Isso pode ser possível com o sed / awk, mas testar a parte numérica provavelmente tornaria isso muito feio.

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
    
por 07.01.2012 / 00:18
3

Se você é apenas preguiçoso como eu e quer fazer tudo em uma linha de comando sem escrever um script, aqui está como eu faria isso.

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

O ^I é feito pressionando ctrl + v i .

O primeiro sed troca todo o tabs por "," . O segundo sed insere um " no início de cada linha, e o último sed insere um " de fechamento no final de cada linha.

    
por 07.01.2012 / 01:28
3

Outra solução 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;

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

    
por 07.01.2012 / 07:27
1

sed é o utilitário linux mais útil que já encontrei.

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

O primeiro comando substitui todas as guias em todas as linhas por vírgulas e aspas. O segundo comando insere aspas no início e no final de cada linha, para que cada valor seja colocado entre aspas, o que permite que as vírgulas façam parte do valor.

    
por 14.07.2017 / 22:49
0

Isso pode funcionar para você:

sed 's/\t\+/,/g;s/^\|$/"/g;s/,/"&"/g;s/"\([0-9]\+\)"/"="/g' file
    
por 22.01.2012 / 22:09