Count Pattern

I need to count the total no of SINY and SINN patterns from the below file , The file does not have a record terminators , data in the file is streamed i.e. one line

I want to put this count in xml structure

<count>
<value>$totalcount</value>
</count>

Tried the following awk statements but since the file does not have any record terminators the output of count is always coming out as 0

awk -F "" '/SIN\*Y\*/{x++;}END{print x >>"count.txt"}' Test.txt
 
count.txt |awk 'BEGIN{print"<Totalcount>"}{print "<value>"$1"</value>"}END { print "</Totalcount>"}'> reccount.txt

Input file Test.txt

 
ISA*xx*xyzzzz    *00*          *0x*xxxxxxxxx      *14*xxxxxxxxxxxxx  *140417*1005*^*00501*xxxxxxxxx*0*P*>~GS*xx*xxxxxxxxx*xxxxxxxxxxxx1*20140417*xxxxxx*xxx*X*005010X220A1~ST*xxx*xxxxxx*005010X220A1~BGN*00*xxxxxxxxxxxxxx*20140417*1005*Ex***4~N1*P5*xxxxxxxxxxxxx*FI*xxxxxxxxx~N1*IN*xxxxxxxx*FI*xxxxxxxxx~SIN*Y*18*xx*XN*A~REF*0F*xxxxxxxxx~REF*1L*xxxxxxxx~REF*ZZ*xxxxxxxxxxxxx~NM1*IL*1*xxxxx*xxxxxxxx*A***ZZ*00~PER*IP**HP*xxxxxxxxxx~N3*xxxxxxxxxxxxxxxxx~N4*xxxxxxxxxxxxxxx*208771193~DMG*xx*xxxxxxxx*x~HD*xxx**xxx*xxx~DTP*xxx*xx*xxxxxxxx~LX*1~NM1*xxxxxxxxx*XX*xxxxxxxxxx*72~PER*xxx*TE*xxxxxxxxxx*FX*xxxxxxxxxx~SIN*N*xx*xxx*XN*A~REF*xx*3xxxxxxxx~REF*xx*xxxxxxx2~REF*xxx00xxxxxxxxxxx~NM1*xxxx*Rxxxxxxx*xxxxxxxx*R***xx*0x~PER*xx**xx*xxxxxxxxxx~N3*xxxxxxxxxxxxxxxxxxD~N4*xxxxxxxxxx*xx*2xxxxxxx8~DMG*xx*xxxxxxx0*x~HD*xx1**xxO*xxx~DTP*xxx*xx*xxxxxxx2~LX*1~NM1*xxx2*xxxxxxxxx Mxxxxxxxxxxxxxxx-xx*******xx~PER*xx**xxxxxxxxxxxx7*xxx*xxxxxxxx6~SE*xx*xxxxxx~GE*x*xxx~IEA*x*0000xxxxx~

Thanks!

If your grep has -o, you can try

$ grep -o 'SIN\*[YN]' input | wc -l
2

otherwise you need to be more resourceful. perhaps:

$ sed 's/SIN\*[YN]/\n&\n/g' input | grep -cx 'SIN\*[YN]'
2
$ perl -lne 'END {print $c} $c += s/SIN\*[YN]//g' input
2

awk

$ awk '{s += gsub(/SIN\*[YN]/,"&")}END{print s}' file
2
$ awk '{s += gsub(/SIN\*[YN]/,"&")}END{f="count.txt";print s >f; close(f)}' test.txt

oh and keeping awk, perhaps:

Removed. Akshay beat me to it

Thanks Akshay!

Can you please explain the code

awk '{s += gsub(/SIN\*[YN]/,"&")}END{print s}' file

function gsub returns the number of substitutions made, variable s holds sum of this count and printed in END block

What is & used for ?

 
awk '{s += gsub(/SIN\*[YN]/,"&")}END{print s}' fileawk '{s += gsub(/SIN\*[YN]/,"&")}END{print s}' file

In a substitution such as gsub in awk or s in sed, & means the matched text itself.

 gsub(r, s [, t])        For each substring matching the regular expres-
                               sion r in the string t, substitute  the  string
                               s,  and return the number of substitutions.  If
                               t is  not  supplied,  use  $0.   An  &  in  the
                           replacement text is replaced with the text that
                           was actually matched.  Use \& to get a  literal
                               &.   (This  must  be  typed as "\\&"; see GAWK:
                               Effective AWK Programming for a fuller  discus-
                               sion  of  the  rules for &'s and backslashes in
                               the replacement text of sub(), gsub(), and gen-
                               sub().)

Thanks for the explanation!

How can I put the value of the count in the below xml structure

 
<count>
<value>$totalcount</value>
</count>

I tried this statement but the xml structure is looping for each input record

count.txt |awk 'BEGIN{print"<Totalcount>"}{print "<value>"$1"</value>"}END { print "</Totalcount>"}'> reccount.txt

why don't you combine all in one like this

awk '{s += gsub(/SIN\*[YN]/,"&")}END{if(s)print "<Totalcount><value>"s"</value></Totalcount>"}' file

Thank you Akshay and Neutronscott!

For 90MB file the above command runs for several minutes , is there a way we can reduce the processing time ?

Thanks

Can anyone optimize the above command , I am ruuning a 90 MB file and it is taking good amount of time to get the count of the pattern

Thanks