perl script to count sepecial characters in a file

Hi - I have a file and it looks like below

ISDFFS*00*          *00*          *30*7984581235      *ZZ*AKLSJFHADSJF   *624654*1805*^*00501*3465465*1*T*:~RS*GS*5145454121*AKLSJFHADSJF*624654*1805*7984581235*X*005010X306~ST*820*7984581235*005010X306~SDF*I*0*C*NON************624654~SDFS*3*99999~SDF*582****RD8*20141201-20141231~SWRE*1121326~RSRRE*RER*ERER**-2132154021.14~DRERF*582****RD8*20150701-20150731~SE*8*7984581235~RT*1*7984581235~IAS*1*7984581235~

Now when I split this file into separate lines using '~' then it looks like below

ISDFFS*00*          *00*          *30*7984581235      *ZZ*AKLSJFHADSJF   *624654*1805*^*00501*3465465*1*T*:~

Now if you observe the below line

The number 8 after SE* means the line count between ST* and SE* (including ST* and SE* lines)

This is simple file so I can count the lines, but for big file with 7 digit number of lines I cannot
so how to write perl script for this.
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

That data file looks impenetrable. Let's pretend that you've got it in a string variable named $datafile (no line breaks).

In a perl script, you could capture all of the line counts in an array with one regular expression match:

my @linecounts = $datafile =~ m/SE\*(\d+)/g;

 Is that something like what you're trying to do?
shragiAuthor Commented:
There are line breaks but in this case it is shown as ~

I want count from ST to SE
Perhaps you could use the .. operator?

$linecount++ if /ST/ .. /SE/;
Determine the Perfect Price for Your IT Services

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden with our free interactive tool and use it to determine the right price for your IT services. Download your free eBook now!

shragiAuthor Commented:
that did not help and did not give the expected count...
i think you misunderstood my question
there is a file with single line text and it can be split into multiple lines using character ~
so now i need to count the number of lines between string that start with

Consider the below example

ISDFFS*00*          *00*          *30*7984581235      *ZZ*AKLSJFHADSJF   *624654*1805*^*00501*3465465*1*T*:~RS*GS*5145454121*AKLSJFHADSJF*624654*1805*7984581235*X*005010X306~ST*820*7984581235*005010X306~SDF*I*0*C*NON************624654~SDFS*3*99999~SDF*582****RD8*20141201-20141231~SWRE*1121326~RSRRE*RER*ERER**-2132154021.14~DRERF*582****RD8*20150701-20150731~SE*123*7984581235~RT*1*7984581235~IAS*1*7984581235~

the number of lines between ~ST* and ~SE* are 8
so i want to replace the string
with ~SE*8*7984581235~

in simple:

count the lines between ~ST* and ~SE*
and replace the string next to ~SE* with the count number.

I wrote the below code and it gave me count 1, can you please correct it


use 5.006;
use strict;
use warnings;
use Pod::Usage;
use Getopt::Long;
use Cwd;
use DateTime;
use DBD::mysql;
use DBI;

my $helpme = 0;
my $man = 0;
my $inputFileName = 'C:\\temp\\script\\TESTPERL.txt';
my $dsn = 'DBI:ODBC:Driver={SQL Server}';
my $host = 'blahblah';
my $database = 'blahblah';
my $user = 'blahblah';
my $auth = 'blahblah';

GetOptions('help' => \$helpme, 'man' => \$man, 'infile=s' => \$inputFileName, 'outfile=s' => \$outputFileName) or pod2usage(2);

pod2usage(1) if $helpme;
pod2usage(-verbose => 2) if $man;

die "No input file name specified!" if !$inputFileName;
die "No output file name specified!" if !$outputFileName;
my $dbh = DBI->connect("$dsn;Server=$host;Database=$database", $user, $auth,{ RaiseError => 1, AutoCommit => 1}) || die "Database connection not made: $DBI::errstr"; 

open(INFILE, "<", $inputFileName) || die "Could not open input file!";

while (<INFILE>) {
 $linecount++ if /ST/ .. /SE/;    

 print $linecount

close INFILE;

Open in new window

$_='ISDFFS*00*          *00*          *30*7984581235      *ZZ*AKLSJFHADSJF   *624654*1805*^*00501*3465465*1*T*:~RS*GS*5145454121*AKLSJFHADSJF*624654*1805*7984581235*X*005010X306~ST*820*7984581235*005010X306~SDF*I*0*C*NON************624654~SDFS*3*99999~SDF*582****RD8*20141201-20141231~SWRE*1121326~RSRRE*RER*ERER**-2132154021.14~DRERF*582****RD8*20150701-20150731~SE*123*7984581235~RT*1*7984581235~IAS*1*7984581235~';

print $linecount = (/(~ST\*.*?~SE\*)/)[0] =~ tr/~/~/;

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Ozo's clearly willing to dive into this deeper than I am. I admit to not understanding very well what you are trying to do.

Your script gets a linecount of 1 because there is only one "line" as perl sees it coming from <INFILE>. By counting the tilde characters that occur in a range between each pair of ST and SE, we can get a count that seems to match what you want. It sounds like you want to then insert this "tilde count" after the SE.

Because it potentially involves multiple substitutions, I hesitate to suggest there might be a way to do it with a single statement.
shragiAuthor Commented:
thanks jmcg and ozo for your time.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.