3

Between first occurrence of Cat to next occurrence of Cat, it should create a separate line with delimiter as ",".

File input as below.

Cat
AA
BB
CC
Cat
AA-1
BB-1
CC-1

Output expected:

Cat,AA,BB,CC
Cat,AA-1,BB-1,CC-1

4 Answers 4

2

With GNU sed:

sed ':a;N;s/\n/,/;ta' file | sed 's/,Cat/\nCAT/g'

or

tr '\n' ',' < file | sed 's/,Cat/\nCAT/g'
2

You could do something like this with sed:

sed '1{h;d;};/^Cat$/!{H;$!d;};x;s/\n/,/g;${x;/^Cat$/H;x;}' infile

explained:

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
1
  • +1 Would you care to expand yr solution by describing sed cmds and script blocks briefly ? (Not for me ... I do have access to info sed ! ;-).
    – Cbhihe
    Commented Jul 24, 2016 at 22:36
2

awk

awk '
    /Cat/ {
        if (NR>1) print ""
        printf "%s", $0
        next
    } 
    {printf ",%s", $0} 
    END {print ""}
' file

Another version that heavily relies on awk variables: (added before I read your comment about "Cat" needing to be a case-insensitive regex)

awk 'BEGIN {RS="Cat"; FS="\n"; OFS=","} NR>1 {$1=RS; NF--; print}' file
0
1

This solution does not require to read the whole file into memory. In other words: It will work on a 1 TB file being processed on a 1 GB machine as long as the full lines are less than 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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .