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
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 Jul 24 '16 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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.