Как я могу преобразовать данные, разделенные табуляцией, в данные, разделенные запятыми?

8

Я запрашиваю список снимков ec2 с помощью инструмента командной строки ec2 amazon:

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
Я думаю, что ваш желаемый результат немного не в порядке. У вас там много пустых полей (пустые кавычки).
Патрик

Ответы:

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}'
Kevin
источник
Хорошее чистое решение. Думал, что все закончится намного ужаснее, но тогда я не акау :-)
Патрик
так я сохраняю это в файл, такой как ./convert.sh, chmod + x, и затем направляю ввод в него так, чтобы это напечатало вывод? Я получаю сообщение об ошибке /usr/bin/awk: syntax error at source line 1 context is >>> . <<< /convert.sh.
CWD
@cwd Вы можете сохранить его в файл, я бы посоветовал convert.awkуказать, что это awkскрипт, а не bashодин. Я обновил запись, указав полную командную строку, и обратите внимание, что -fв первую строку я добавил забытый флаг (который говорит о том, что файл следует интерпретировать как команды).
Кевин
В однострочном варианте любой пробел рассматривается как разделитель полей, а не как вкладки. Требуется -F '\ t' до -V.
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 Синтаксис есть <kbd>text</kbd>.
jw013
3
Или в одну строку: sed -e 's/^I/","/g' -e 's/.*/"&"/'или даже короче sed -e 's/^I/","/g;s/.*/"&"/'.
Arcege
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.
Патрик
Правда. Извиняюсь за плохую формулировку моего предполагаемого комментария. Спасибо за исправление.
Джим
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
Potong
источник