Есть много способов достичь этого:
с трубами:
sed "s/.*/'&'/" <file> | paste -sd,
awk '{print '"'"'$0'"'"'}' <file> | paste -sd,
примечание: мы не используем здесь tr
, так как это приведет к дополнительному ,
в конце.
чтение полного файла в память:
sed ':a;N;$!ba;s/\n/'"','"'/g;s/.*/'"'&'"'/g' <file> #POSIX
sed -z 's/^\|\n$/'"'"'/g;s/\n/'"','"'/g;' <file> #GNU
и решение @ EdMorton
без считывания полного файла в память:
awk '{printf (NR>1?",":"")"\047"$0"\047"}' <file>
и некоторые другие случайные попытки:
awk '(NR-1){s=s","}{s=s"\047"$0"\047"}END{print s}' <file>
awk 'BEGIN{printf s="\047";ORS=s","s}(NR>1){print t}{t=$0}END{ORS=s;print t} <file>
Так что же происходит с попытками ОП?
Записывая строку awk ОП, мы имеем
/START/{if (x)print x;x="";next}
{x=(!x)?$0:x","$0;}
END{print x;}
Что это делает? Давайте проанализируем шаг за шагом:
/START/{if (x)print x;x="";next}
:: Это читается как Если текущая запись / строка содержит строку START
, тогда выполните
if (x) print x
:: если x
не является пустой строкой, выведите значение x
x=""
установить x
в качестве пустой строки
next
:: перейти к следующей записи / строке
В этом кодовом блоке OP, вероятно, предполагал, что /START/
означает, что делает это в начале всех вещей . В awk это записывается как BEGIN
, и поскольку в начале все переменные являются пустыми строками или нулем, оператор if по умолчанию не выполняется. Этот блок может быть заменен на:
BEGIN{x=""}
Но опять же, это не нужно, и, таким образом, его можно удалить:
{x=(!x)?$0:x","$0;}
:: объединить строку с правильным разделителем. Это хорошо, особенно из-за использования троичного оператора. К сожалению, разделитель установлен на ,
, а не ','
, который в awk лучше всего записать как \047,\047
. Таким образом, строка может читать:
{x=(!x)?$0:x"\047,\047"$0;}
Эта строка может быть написана короче, если вы понимаете, что x
может быть пустой строкой. Для пустой строки x=$0
эквивалентно x=x $0
, и все, что вы хотите сделать, это добавить разделитель, который может быть пустой строкой или не содержать ее. Таким образом, вы можете написать это как
{x= x ((!x)?"":"\047,\047") $0}
или инвертирование логики, чтобы избавиться от еще нескольких символов:
{x=x(x?"\047,\047":"")$0}
можно даже написать
{x=x(x?"\047,\047":x)$0}
но это не оптимально, так как нужно снова прочитать, что такое память x
. Однако эта форма может быть использована для окончательной оптимизации (согласно @ комментарию EdMorton )
{x=(x?x"\047,\047":"")$0}
Это лучше, так как убирает лишний оператор конкатенации.
END{print x}
:: Здесь OP печатает результат. Однако при этом будут пропущены заключительные одинарные кавычки в начале и конце строки, поэтому их можно добавить
END{print "\047" x "\047"}
Таким образом, исправленная версия кода ОП будет выглядеть так:
awk '{x=(x?x"\047,\047":"")$0}END{print "\047" x "\047"}'