Объедините строки в одну строку, используя awk - PullRequest
0 голосов
/ 06 сентября 2018

У меня есть файл со следующими записями

ABC
BCD
CDE
EFG

Я хотел бы преобразовать это в

'ABC','BCD','CDE','EFG'

Я попытался атаковать эту проблему с помощью Awk следующим образом:

awk '/START/{if (x)print x;x="";next}{x=(!x)?$0:x","$0;}END{print x;}'

но я получаю не то, что ожидал:

ABC,BCD,CDE,EFG

Есть ли какие-либо предложения о том, как этого добиться?

Ответы [ 4 ]

0 голосов
/ 06 сентября 2018

Есть много способов достичь этого:

с трубами:

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"}'
0 голосов
/ 06 сентября 2018

awk может быть лучше

awk '{printf fmt,$1}' fmt="'%s'\n" file | paste -sd, -

'ABC','BCD','CDE','EFG'
0 голосов
/ 06 сентября 2018

С GNU awk для нескольких символов RS:

$ awk -v RS='\n$' -F'\n' -v OFS="','" -v q="'" '{$1=$1; print q $0 q}' file
'ABC','BCD','CDE','EFG'
0 голосов
/ 06 сентября 2018

Не могли бы вы попробовать следующее.

awk -v s1="'" 'BEGIN{OFS=","} {val=val?val OFS s1 $0 s1:s1 $0 s1} END{print val}' Input_file

Вывод будет следующим.

'ABC','BCD','CDE','EFG'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...