same code diff result

A

Amaninder

Hi everyone

I tried lot of things but can not able to figure out why the same code
in for loop is giving me different results.
Code 1 is giving me the correct result but Code 2 does NOT. All i am
doing in ths Code 1 is that i have
my $got = "3 500 1660 17800 19360 N";
my $exp = "<0 3> <0 500> <0 1660> 17800 19360 <0
N>";

and i am filling @btw with ('"0 3". "3", "0 500", "500", "0 N" ,
"N").

Now the code in "Code 2" is same except it is funtion and i am
receiving $got and $exp as a parameters.

Problem is in "Code 2" $got =~ s/$split[$i]//; deletes the content of
$got whereas in "Code 1" it does NOT when lenght of $split[$i] = 0 in
both cases.


####################Code 1 #######################################
#!/usr/bin/perl -w
use strict;

sub trim($)
{
my $string = shift;
if (defined($string) ){
$string =~ s/^\s+//;
$string =~ s/\s+$//;

}
return $string;
}


my @btw;
my $errMess;
my $got = "3 500 1660 17800 19360 N";
my $exp = "<0 3> <0 500> <0 1660> 17800 19360 <0
N>";
my @split = split(/<|>/, $exp);


for(my $i = 0; $i <= $#split; $i=$i+2){
if($i+1 > $#split){
last;
}
push (@btw, $split[$i + 1]);
$split[$i] = trim ($split[$i]);
$got =~ s/$split[$i]//;

if ( $i + 2 > $#split){
push (@btw, $got);
}else{
$split[$i + 2] = trim ($split[$i + 2]);
#in freq one if $split[$i + 2]= ' ' , then trim will delete
all the
#space and leave it to nothing. length = 0
#Therefore, if lenght is 0 let $split[$i + 2] = ' ', so that
$point != 0
if( length ($split[$i + 2]) == 0){
$split[$i + 2] = ' ';
}
my $point = index $got, $split[$i + 2];
if( $point == -1){
$errMess = sprintf ( "'%s' is NOT found", $split[$i + 2]);
last;
}elsif($point == 0){
$errMess = sprintf ( ">,< should NOT be together");
last;
}
push (@btw, substr $got, 0, $point, '');
$got = trim ($got);
}
}

foreach my $temp (@btw){
printf ("\n%s", $temp?$temp:'');
}
printf ("\n%s.", $errMess?$errMess:'');








#####################Code 2###################################
sub compareLines{
my $exp = shift;
my $got = shift;
#default is pass
my $passOrFail = 'pass';
my $errMess;



my @split = split(/<|>/, $exp);
my @btw;

for(my $i = 0; $i <= $#split; $i=$i+2){
if($i+1 > $#split){
last;
}
push (@btw, $split[$i + 1]);
$split[$i] = trim ($split[$i]);
$got =~ s/$split[$i]//;

if ( $i + 2 > $#split){
push (@btw, $got);
}else{
$split[$i + 2] = trim ($split[$i + 2]);
#in freq one if $split[$i + 2]= ' ' , then trim will
delete all the
#space and leave it to nothing. length = 0
#Therefore, if lenght is 0 let $split[$i + 2] = ' ', so
that $point != 0
if( length ($split[$i + 2]) == 0){
$split[$i + 2] = ' ';
}
my $point = index $got, $split[$i + 2];
if( $point == -1){
$errMess = sprintf ( "compareLines(): '%s' is NOT
found", $split[$i + 2]);
last;
}elsif($point == 0){
$errMess = "compareLines(): >,< should NOT be
together";
last;
}
push (@btw, substr $got, 0, $point, '');
$got = trim ($got);
}
}

#if there is any error return
if( defined ($errMess) && $errMess =~ /.+/){
return ($errMess, $passOrFail);
}

#send to compare elements in the array
($errMess, $passOrFail) = compareElemArray(\@btw);

if( defined ($errMess) && $errMess =~ /.+/){
# add compareLines
$errMess = "compareLines(): $errMess";
}

return ($errMess, $passOrFail);
}


Regards
Amaninder Saini :)
 
J

John W. Krahn

Amaninder said:
I tried lot of things but can not able to figure out why the same code
in for loop is giving me different results.
Code 1 is giving me the correct result but Code 2 does NOT. All i am
doing in ths Code 1 is that i have
my $got = "3 500 1660 17800 19360 N";
my $exp = "<0 3> <0 500> <0 1660> 17800 19360 <0
N>";

and i am filling @btw with ('"0 3". "3", "0 500", "500", "0 N" ,
"N").

I get the same results as your program using this:

$ perl -le'
my $exp = "<0 3> <0 500> <0 1660> 17800 19360 <0 N>";
my @btw = $exp =~ /<(\S.*?(\S+))>/g;
print for @btw;
'
0 3
3
0 500
500
0 1660
1660
0 N
N


You probably need to simplify your code.


John
 
A

Amaninder

John said:
I get the same results as your program using this:

$ perl -le'
my $exp = "<0 3> <0 500> <0 1660> 17800 19360 <0 N>";
my @btw = $exp =~ /<(\S.*?(\S+))>/g;
print for @btw;
'
0 3
3
0 500
500
0 1660
1660
0 N
N


You probably need to simplify your code.


John

Sweet

How about if
my $got = "d 500 166 17800 19360 N";
my $exp = "<s 3> 500 <a 1660> 17800 19360
<XXX>";

and output will be

s 3
d
a 1660
166
XXX
N

Thanks
Amaninder :)
 
J

John W. Krahn

Amaninder said:
How about if
my $got = "d 500 166 17800 19360 N";
my $exp = "<s 3> 500 <a 1660> 17800 19360
<XXX>";

and output will be

s 3
d
a 1660
166
XXX
N

$ perl -le'
my $got = "d 500 166 17800 19360 N";
my $exp = "<s 3> 500 <a 1660> 17800 19360 <XXX>";

$exp =~ s/(<\S+)( )(?=\S+>)/$1\0/g; # preprocess

my @gots = split " ", $got;
my @exps = split " ", $exp;

my @btw;
for my $i ( 0 .. $#exps ) {
next unless $exps[ $i ] =~ tr/\0<>/ /d;
push @btw, $exps[ $i ], $gots[ $i ];
}

print for @btw;
'
s 3
d
a 1660
166
XXX
N




John
 
A

Amaninder

John said:
Amaninder said:
How about if
my $got = "d 500 166 17800 19360 N";
my $exp = "<s 3> 500 <a 1660> 17800 19360
<XXX>";

and output will be

s 3
d
a 1660
166
XXX
N

$ perl -le'
my $got = "d 500 166 17800 19360 N";
my $exp = "<s 3> 500 <a 1660> 17800 19360 <XXX>";

$exp =~ s/(<\S+)( )(?=\S+>)/$1\0/g; # preprocess

my @gots = split " ", $got;
my @exps = split " ", $exp;

my @btw;
for my $i ( 0 .. $#exps ) {
next unless $exps[ $i ] =~ tr/\0<>/ /d;
push @btw, $exps[ $i ], $gots[ $i ];
}

print for @btw;
'
s 3
d
a 1660
166
XXX
N




John

Hey John
That's just brilliant. Could you tell me how do you add \x in all <>.
Moreover, what does the following code work?
I know ? is for once or not at all and /0 is maybe for memory, but i
dont know what is '$1' and '=' doing here?
$exp =~ s/(<\S+)( )(?=\S+>)/$1\0/g; # preprocess

Also, what is /0 doing in the following
next unless $exps[ $i ] =~ tr/\0<>/ /d;


Thanks for your help
Amaninder Saini
 
J

John W. Krahn

John said:
Amaninder said:
How about if

my $got = "d 500 166 17800 19360 N";
my $exp = "<s 3> 500 <a 1660> 17800 19360
<XXX>";

and output will be

s 3
d
a 1660
166
XXX
N

$ perl -le'
my $got = "d 500 166 17800 19360 N";
my $exp = "<s 3> 500 <a 1660> 17800 19360 <XXX>";

$exp =~ s/(<\S+)( )(?=\S+>)/$1\0/g; # preprocess

my @gots = split " ", $got;
my @exps = split " ", $exp;

my @btw;
for my $i ( 0 .. $#exps ) {
next unless $exps[ $i ] =~ tr/\0<>/ /d;
push @btw, $exps[ $i ], $gots[ $i ];
}

print for @btw;
'
s 3
d
a 1660
166
XXX
N

And you could do that without splitting the strings:

john@d154-20-154-176:~> perl -le'
my $got = "d 500 166 17800 19360 N";
my $exp = "<s 3> 500 <a 1660> 17800 19360 <XXX>";

$exp =~ s/(<\S+)( )(?=\S+>)/$1\0/g; # preprocess

my @btw;
{ my ( $got1, $exp1 );
$got =~ /\G(\S+)\s*/gc and $got1 = $1 and
$exp =~ /\G(\S+)\s*/gc and $exp1 = $1 and
do { $exp1 =~ tr/\0<>/ /d and push @btw, $exp1, $got1; $exp1 } and redo
}

print for @btw;
'
s 3
d
a 1660
166
XXX
N



John
 
J

John W. Krahn

Amaninder said:
John said:
$ perl -le'
my $got = "d 500 166 17800 19360 N";
my $exp = "<s 3> 500 <a 1660> 17800 19360 <XXX>";

$exp =~ s/(<\S+)( )(?=\S+>)/$1\0/g; # preprocess

my @gots = split " ", $got;
my @exps = split " ", $exp;

my @btw;
for my $i ( 0 .. $#exps ) {
next unless $exps[ $i ] =~ tr/\0<>/ /d;
push @btw, $exps[ $i ], $gots[ $i ];
}

print for @btw;
'
s 3
d
a 1660
166
XXX
N

Hey John
That's just brilliant. Could you tell me how do you add \x in all <>.
Moreover, what does the following code work?
I know ? is for once or not at all and /0 is maybe for memory, but i
dont know what is '$1' and '=' doing here?
$exp =~ s/(<\S+)( )(?=\S+>)/$1\0/g; # preprocess

The pattern says match the expression '<\S+' and capture it in the $1 variable
and then match a single space character and capture it in the $2 variable (we
don't use $2 so it is not necessary to capture it) and then match '\S+>' using
a zero-width positive look-ahead assertion (?=). The single space character
is replaced with the "\0" (ASCII NULL) character so it won't be matched when
the string is split() into an array.

Also, what is /0 doing in the following
next unless $exps[ $i ] =~ tr/\0<>/ /d;

All of the "\0" characters are replaced with ' ' characters and all '<' and
'>' characters are removed.

For more information on how the s/// and tr/// operators work:

perldoc perlop
perldoc perlre



John
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top