Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Reg Ex exercise

by keesturam (Initiate)
on Dec 05, 2012 at 16:07 UTC ( [id://1007311]=perlquestion: print w/replies, xml ) Need Help??

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

I am practicing few Regex exercises, one was this, Use regular expressions (RE) to check that the data you get when asking for numbers, are actually numbers. Also check that the operation is valid. These should all be considered as numbers: "4" "-7" "0.656" "-67.35555" These are not numbers: "5." "56F" ".32" "-.04" I have come up with this code, although I know it is not the best way. Can you suggest a better way to search in a single go rather than using OR?
print ("Enter the number to check if it is actually a number:"); $input = <STDIN>; while ($input ne "") { chop ($input); if ($input =~ /^\d+$/ | $input =~ /^\d+.\d+$/ | $input =~ /^-\d+$/ | $ +input =~ /^-\d+.\d+$/) { print ("Yes, it is a number\n"); } else { print ("No, it is not a number\n"); } print ("Give another input:"); $input = <STDIN>; }

Replies are listed 'Best First'.
Re: Reg Ex exercise
by choroba (Cardinal) on Dec 05, 2012 at 16:28 UTC
    | stands for "or" only inside a regular expression. Outside, you have to use || or or. The vertical bar alone is a "bitwise or", see perlop. No "or" is needed, though:
    #!/usr/bin/perl use warnings; use strict; use Test::More; my $r = qr/^-? # Can start with a minus. (:? # Non capturing group. [0-9]+ # Digits. Does not match Unicode digits as \d + does. (?: # Another group, this one will be optional. \. # The dot. Backslashed to lose its special me +aning. [0-9]+ # Digits again. )? # End of the inner group, the ? makes it opti +onal. ) # End of the outer group. $ # And nothing more. /x; like ($_, $r) for qw/ 4 -7 0.656 -67.35555 /; unlike($_, $r) for qw/ 5. 56F .32 -.04 /; done_testing();
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: Reg Ex exercise
by toolic (Bishop) on Dec 05, 2012 at 16:44 UTC
    From Scalar::Util::looks_like_number
    perldoc -m Scalar::Util::PP sub looks_like_number { local $_ = shift; # checks from perlfaq4 return 0 if !defined($_); if (ref($_)) { require overload; return overload::Overloaded($_) ? defined(0 + $_) : 0; } return 1 if (/^[+-]?[0-9]+$/); # is a +/- integer return 1 if (/^([+-]?)(?=[0-9]|\.[0-9])[0-9]*(\.[0-9]*)?([Ee]([+-]?[ +0-9]+))?$/); # a C float return 1 if ($] >= 5.008 and /^(Inf(inity)?|NaN)$/i) or ($] >= 5.006 +001 and /^Inf$/i); 0; }
Re: Reg Ex exercise
by thundergnat (Deacon) on Dec 05, 2012 at 16:26 UTC

    Seems like fairly arbitrary specs for what is or isn't a number. Ah well. Don't expect this to work for scientific notation, complex numbers, or anything else that isn't explicitly tested here.

    printf "%s is %sa number.\n", $_, /^-?\d+(?:\.\d+)?$/ ? '' : 'NOT ' for qw/4 -7 0.656 -67.35555 5. 56F .32 -.04/;
    4 is a number.
    -7 is a number.
    0.656 is a number.
    -67.35555 is a number.
    5. is NOT a number.
    56F is NOT a number.
    .32 is NOT a number.
    -.04 is NOT a number.
    
Re: Reg Ex exercise
by 2teez (Vicar) on Dec 05, 2012 at 16:28 UTC

    You will want to use chomp, not chop.
    Then you can put all your codes within a while loop more constructively.

    If you tell me, I'll forget.
    If you show me, I'll remember.
    if you involve me, I'll understand.
    --- Author unknown to me
Re: Reg Ex exercise
by Rudolf (Pilgrim) on Dec 05, 2012 at 16:18 UTC

    Hello keesturam, Im sure it could be simplified more, but this is what I came up with! hope it helps :)

    if($input =~ /^(-?)((0|\d+).)?\d+$/) { print ("Yes, it is a number\n"); }

    UPDATE: don't need that 0 in there,

    if($input =~ /^(-?)(\d+.)?\d+$/)

      Um... You need to escape that full stop.

      >perl -e "print 'match' if '1234X789' =~ /^(-?)(\d+.)?\d+$/"
      match
      

      Thanks Rudolf, that was really helpful.

      I am simply not able to come up with such regexs. I should practice more and more and more..! :-)

Re: Reg Ex exercise
by BillKSmith (Monsignor) on Dec 05, 2012 at 18:08 UTC
    I understand that your purpose here is practice in writting regular expressions. You probably have already noticed that numbers can be tricky. In production work, use a module Regexp::Common
    Bill
Re: Reg Ex exercise
by Athanasius (Archbishop) on Dec 05, 2012 at 16:28 UTC
    #! perl use Modern::Perl; while (<DATA>) { chomp; if (/ ^ (?: (?: -? \d+) | (?: -? \d+ \. \d+)) $ /x) { say 'Yes, ', $_, ' is a number'; } else { say 'No, ', $_, ' is not a number'; } } __DATA__ 4 -7 0.656 -67.35555 5. 56F .32 -.04

    Output:

    2:17 >perl 417_SoPW.pl Yes, 4 is a number Yes, -7 is a number Yes, 0.656 is a number Yes, -67.35555 is a number No, 5. is not a number No, 56F is not a number No, .32 is not a number No, -.04 is not a number 2:17 >

    Some notes:

    • | is bitwise-OR outside a regex, and alternation in a regex. For logical OR, use || (or or).

    • Within a regex, a dot matches any character. To match the decimal point, you need to escape it: “\.”.

    • Prefer chomp to chop — the former removes a line-termination if present, the latter removes the last character regardless.

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: Reg Ex exercise
by grondilu (Friar) on Dec 05, 2012 at 16:29 UTC

    You can put your OR inside your regex:

    use strict; use warnings; print "Enter the number to check if it is actually a number: "; while (<STDIN>) { chomp; if (/^(\d+|\d+.\d+|-\d+|-\d+.\d+)$/) { print "Yes, it is a number\n"; } else { print "No, it is not a number\n"; } print "Give another input: "; }

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1007311]
Approved by bitingduck
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (5)
As of 2024-03-28 11:06 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found