tags:

views:

154

answers:

4

I am searching for a string in Perl and storing it in another scalar variable. I want to print this scalar variable. The code below doesn't seem to work. I am not sure what is going wrong and what is the right way to go about it. Why is it printing '1' when it doesn't exist in the program?

Data it is running on

DATA

      13 E 0.496 -> Q 0.724
      18 S 0.507 -> R 0.513
      19 N 0.485 -> S 0.681
      21 N 0.557 -> K 0.482

The following is my code:

#!/usr/bin/perl
use strict;
use warnings;

my $find = '\s{10}[0-9]{2}\s[A-Z]'; #regex. it can also be '\s{10}[0-9]{2}\s[A-Z]' 
                                    #both dont seem to work
my @element;
open (FILE, "/user/run/test") || die "can't open file \n";
while (my $line = <FILE>) {
    chomp ($line);
    print "reached here1 \n"; # to test whether it reading the program properly
    my $value = $line=~ /$find/ ;
    print "reached here 3 \n"; # to test whether it reading the program properly
    print "$value \n";
}
exit;

OUTPUT

reached here1

1 

reached here 3 

reached here1 

1 

reached here 3
+5  A: 

The regex matching operation returns true (1) for match success, false otherwise. If you want to retrieve the match, you should try one of the following:

  • use the match variables $1, $2...
  • match in list context ($m1, $m2) = $string =~ /$regex/

Note that you need to use captures in your regex for these to work. Which you're not doing yet.

You ought to take a look at the complete documentation in perlop, section "Regexp Quote-Like Operators"

JB
A: 

I'm unable to replicate your results. What I get is:

reached here1 
reached here 3 
1 
reached here1 
reached here 3 
1 
reached here1 
reached here 3 
1 
reached here1 
reached here 3 
1

Regardless, it's printing 1 because you've told it to: the print statement to do so is inside the while loop, and what it's printing is an indication of whether or not the pattern matched.

You'd benefit from indenting your code properly:

#!/usr/bin/perl
use strict;
use warnings;

my $find = '\s{10}[0-9]{2}\s[A-Z]'; #regex. it can also be '\s{10}[0-9]{2}\s[A-Z]' 
                                    #both dont seem to work
my @element;
open (FILE, "foo") || die "can't open file \n";
while (my $line = <FILE>) {
    chomp ($line);
    print "reached here1 \n"; # to test whether it reading the program properly
    my $value = $line=~ /$find/ ;
    print "reached here 3 \n"; # to test whether it reading the program properly
    print "$value \n";
}
exit;
chaos
+2  A: 

JB is correct. Your regular expression would need to use captures (which are defined by parentheses) for the individual parts to be collected. If you want to capture all of the elements in your line, you would want this:

my $find = '\s{10}([0-9]{2})\s([A-Z])';
my $field1;
my $field2;
while (my $line = <FILE>) {
   chomp ($line);
   if ($line=~ /$find/) {
      $field1 = $1;
      $field2 = $2;
      # Do something with current line's field 1 and field 2
   }
}
Tony Miller
+1  A: 

m// returns the captured matches in list context:

#!/usr/bin/perl

use strict;
use warnings;

my $pattern = qr/^\s{10}([0-9]{2})\s[A-Z]/;

while ( my $line = <DATA> ) {
    if ( my ($n) = $line =~ $pattern ) {
        print "$n\n";
    }
}

__DATA__
          13 E 0.496 -> Q 0.724
          18 S 0.507 -> R 0.513
          19 N 0.485 -> S 0.681
          21 N 0.557 -> K 0.482
Sinan Ünür