Вы можете сделать это с помощью Perl
с помощью функции unpack
, создав шаблон распаковки динамически, изучив заголовок (1-я строка):
perl -lpe '
$fmt //= join "", map("A". length(), /\H+\h+(?=\H)/g), "A*";
$_ = join ",", map { s/"/""/gr =~ s/(.*)/"$1"/r } unpack $fmt;
' input-file.txt
Пояснение:
-p
заставит perl
потреблять файл на основе -строк. Каждая строка, также известная как запись, обозначается как $_
. Другой эффект -p
заключается в том, что он автоматически печатает текущую запись, прежде чем перейти к выборке следующей. -l
делает 2 вещи, устанавливаетORS = RS = \n
/\H+\h+(?=\H)/g
должно извлекать все поля, кроме последнего, а затем они передаются в map
. map
вычисляет длины этих полей и добавляет к каждому префикс «А». join
, который склеивает их вместе в строку, используя нулевой разделитель. Таким образом, формат распаковки готов к использованию и больше не вычисляется из-за оператора //=
, который является функцией defined-or
. unpack
распаковывает строку, в нашем случае текущую строку, используя предоставленный формат, и выдает распакованные поля. map
, который работает с каждым -за -единицей и выполняет шаги, описанные в коде {... }
. В нашем случае в каждом поле мы делаем следующее :a )удваиваем двойные кавычки. b )заключите поле в двойные кавычки. map
закончит редактирование полей, он перебрасывает их в join
, который объединяет их с помощью запятой ,
и формирует небольшой CSV
файл. unpack
, потому что unpack
делает это за вас при использовании символа форматированияA
(A для ASCII ). Выход:
"Id","Name","Type","Size","Created"
"1sV3_a1ySV0-jbLxhA8NIEts1KU_aWa-5","info.pdf","bin","10.0 B","2018-08-27 20:26:20"
"1h-j3B5OLryp6HkeyTsd9PJaAtKK_GYyl","2018-12-ss-scalettapass","dir","","2018-08-27 20:26:19"
Это можно сделать с помощью инструмента sed
, но потребуется двухпроходный -подход, в котором сначала, используя строку заголовка ввода, мы динамически генерируем скрипт sed
, который затем работает с входной файл (, включая заголовок )для выполнения желаемой операции, как показано:
if="input-file.txt"
cmd=$(< "$if" head -n 1 | perl -lne 'print join $/, reverse map { $s += length();qq[s/./\\n/$s] } /\H+\h+(?=\H)/g')
sed -e '
'"${cmd}"'
s/"/""/g
s/[[:blank:]]*\n/","/g
s/.*/"&"/
' < "$if"