Com o GNU sed:
sed ':a;N;s/\n/,/;ta' file | sed 's/,Cat/\nCAT/g'
ou
tr '\n' ',' < file | sed 's/,Cat/\nCAT/g'
Entre a primeira ocorrência de Cat
até a próxima ocorrência de Cat
, ele deve criar uma linha separada com delimitador como ",".
Entrada de arquivo como abaixo.
Cat
AA
BB
CC
Cat
AA-1
BB-1
CC-1
Resultado esperado:
Cat,AA,BB,CC
Cat,AA-1,BB-1,CC-1
Com o GNU sed:
sed ':a;N;s/\n/,/;ta' file | sed 's/,Cat/\nCAT/g'
ou
tr '\n' ',' < file | sed 's/,Cat/\nCAT/g'
awk
awk '
/Cat/ {
if (NR>1) print ""
printf "%s", $0
next
}
{printf ",%s", $0}
END {print ""}
' file
Outra versão que depende muito de variáveis awk: (adicionado antes de ler seu comentário sobre "Cat" precisando ser um regex sem distinção entre maiúsculas e minúsculas)
awk 'BEGIN {RS="Cat"; FS="\n"; OFS=","} NR>1 {$1=RS; NF--; print}' file
Esta solução não requer a leitura de todo o arquivo na memória. Em outras palavras: ele funcionará em um arquivo de 1 TB sendo processado em uma máquina de 1 GB, contanto que as linhas completas sejam menores que 1 GB.
perl -ne 'BEGIN { $sep = shift; }
if(/^$sep$/o) { @p and print join(",", @p)."\n"; @p = (); }
chomp; push @p, $_;
END { print join(",", $sep, @p)."\n"; }' Cat /tmp/cat
Você poderia fazer algo assim com sed
:
sed '1{h;d;};/^Cat$/!{H;$!d;};x;s/\n/,/g;${x;/^Cat$/H;x;}' infile
explicado:
sed '1{ # if this is the 1st line
h # copy over the hold space
d # and delete it
}
/^Cat$/!{ # if the line doesn't match Cat
H # append to hold space and
$!d # delete it if it's not the last line
}
x # exchange pattern space w. hold buffer
s/\n/,/g # replace all newline chars with commas
${ # check if the last line of input matches Cat:
x # exchange pattern space w. hold buffer
/^Cat$/H # if the line matches Cat append it to hold buffer
x # exchange back
}' infile
Tags text-processing perl awk sed