perlDevsWorld has asked for the wisdom of the Perl Monks concerning the following question:

I'm running into issue while reading a file and matching the pattern

File content ============ 1: Recturing Svc 2: Finance : : 9: Payments : : 19: Mobile : : 29: Bankers

My Code looks like this

open(INPUTFILE,"<$conf_file") or die("unable to open text file"); foreach (<INPUTFILE>) { print "$_"; } close INPUTFILE ; print "Please choose a number from the list above: "; chop($input=<STDIN>); $input=trim($input); print "Your Choice was: $input \n"; $TEMP="$input:"; open(INPUTFILE,"<$conf_file") or die("unable to open text file for com +parision"); foreach $line(<INPUTFILE>) { if($line =~ /$TEMP/) { print " exact match: $& \n" ; print " after match: $' \n" ; $svc = $'; print "ServiceL $svc \n"; } } close INPUTFILE ;

As said it is matching multiple ones for example 9: and 19: and 29: when I select i.e. enter 9

Replies are listed 'Best First'.
Re: pattern string match while reading from the file
by kennethk (Abbot) on Apr 09, 2015 at 19:45 UTC
    I'd probably use word boundaries. This not only address the 19 problem, but also pme's concerns about 90. It would presume your summaries do not contain numbers surrounded by punctuation or whitespace.

    Also, as you are taking an arbitrary string as input, you might want to use quotemeta to escape special characters.

    if($line =~ /\b\Q$TEMP\E\b/) {

    Other nice additions might include three-argument open, indirect file handles, and the strict pragma.

    !/usr/bin/perl use strict; use warnings; my $conf_file = 'something'; open(my $in,'<', $conf_file) or die("unable to open $conf_file"); my @lines = <$in>; print @lines; print "Please choose a number from the list above: "; chomp(my $input = <STDIN>); # $input=trim($input); print "Your Choice was: $input \n"; for my $line (@lines) { if ($line =~ /\b\Q$input:\E\b/) { print " exact match: $& \n" ; print " after match: $' \n" ; my $svc = $'; print "ServiceL $svc \n"; } }

    #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

Re: pattern string match while reading from the file
by AnomalousMonk (Archbishop) on Apr 09, 2015 at 21:03 UTC

    Another approach: File select_1.pl:

    use warnings; use strict; use Data::Dump; # for development/debug # you will have to open and process some kind of config file, # but i will use __DATA__ my %services; while (my $record = <DATA>) { my ($n, $service) = $record =~ m{ \A (\d+) \s* : \s* (.*?) \s* \z }xms; if (! defined($n) or ! defined($service)) { die "bad config file record '$record'" } if (exists $services{$n}) { die "duplicated service number $n: '$service'"; } $services{$n} = $service; } # dd \%services; # FOR DEBUG print "$_: $services{$_} \n" for sort { $a <=> $b } keys %services; my $n; CHOICE: { print "Please choose a number from the list above: "; chomp($n = <STDIN>); last CHOICE if exists $services{$n}; print "'$n' is not on the list. Please choose again. \n"; redo CHOICE; } print "You chose $n: '$services{$n}' \n"; __DATA__ 1: Recturing Svc 2: Finance 9: Payments 19: Mobile 29: Bankers
    Output:
    c:\@Work\Perl\monks\perlDevsWorld>perl select_1.pl 1: Recturing Svc 2: Finance 9: Payments 19: Mobile 29: Bankers Please choose a number from the list above: 3 '3' is not on the list. Please choose again. Please choose a number from the list above: xx 'xx' is not on the list. Please choose again. Please choose a number from the list above: 9 You chose 9: 'Payments'


    Give a man a fish:  <%-(-(-(-<

      I think that this approach is much better than anything before (and I would have suggested something along the same line if you had not done it).

      Storing the data in a hash (or possibly an array) makes it possible to have instant in-memory access to the data, instead of having to read through the file each time over.

      Je suis Charlie.
Re: pattern string match while reading from the file
by pme (Monsignor) on Apr 09, 2015 at 19:15 UTC
    You can anchor the match to the beginning of the string:
    if($line =~ /^$TEMP/) { # ^
    Of course having item 90 will cause the same problem. For more details see: perlre, perlretut
Re: pattern string match while reading from the file
by CountZero (Bishop) on Apr 09, 2015 at 20:30 UTC
    And use 'chomp' rather than 'chop'.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

    My blog: Imperial Deltronics
Re: pattern string match while reading from the file
by hdb (Monsignor) on Apr 09, 2015 at 20:18 UTC

    If you want to pick a line based on the number, you should extract that number from the line and then do a numerical comparison:

    $line=~/^(\d+):/; if( $1==$input ){ ...
Re: pattern string match while reading from the file
by gpapkala (Acolyte) on Apr 09, 2015 at 20:03 UTC
    If you're expecting the number as the input, and there is one item per one line in your file, it seems to me you do not need the pattern matching at all. If someone enters 9, just give him 11th line from the file (taking into account two lines with header).