Sumit
Sumit

Reputation: 2023

Matching IP in perl

I use this code to match IP

$IP =~ /(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/;

if ( $1 < 256 && $2 < 256 && $3 < 256 && $4 < 256) {
print "IP matched";
}

I don't want to use if loop. Is there a way we can do the checking ( < 256) in regexp only

I know there is another way like

/25[0-5]|2[0-4][0-9]|[01][0-9][0-9]?/

Is there a another shortcut way

Upvotes: 2

Views: 129

Answers (5)

Samiron
Samiron

Reputation: 5317

I can understand you are asking about a regex for validating IP address? But why don't you try http://metacpan.org/pod/Data::Validate::IP instead of manual approaches?

Upvotes: 1

amon
amon

Reputation: 57590

Embedded code can be used as a condition inside a regex, and certain branches can be made to force backtracking:

qr/
  # the string consists of nothing but 4 bytes separated by a period
  \A (?&decimal_byte) (?: [.] (?&decimal_byte) ){3} \z

  (?(DEFINE)
    (?<decimal_byte>
      ([0-9]{1,3}+)  # 1 to 3 digits without backtracking
      (?(?{ $^N <= 0xFF }) | (*FAIL) )  # (?(?{ COND }) YES | NO )
    )
  )
/x

The $^N refers to the last closed capture group. Note that evaluating code inside regexes has security repercussions1, and that this technique is not portable to other regex engines like pcre.


  1. If you blindly interpolate an untrusted regex, it could execute arbitrary code:

    my $malicious = '(?{ `rm -rf ~` })';
    
    say "You were pwned" if $foo =~ /something="$malicious"/;
    

    Perl saves you from regex security hell by requiring that you use re qw/eval/ if you want to be responsible for regex security yourself. Note that this is only necessary if the interpolation triggers a new compilation: my $ok = qr/(?{ say "yes" })/; $foo =~ /$ok/ works just fine.

Upvotes: 0

mpapec
mpapec

Reputation: 50637

Look at @ysth answer or you can store matches into array:

my @m = grep $_ <256, $IP =~ /([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/;

if (@m == 4) {
  print "IP matched";
}

Upvotes: 2

ysth
ysth

Reputation: 98378

use Regexp::Common 'net';

if ( $IP =~ /\A$RE{net}{IPv4}\z/ ) {
    print "IP matched\n";
}

Upvotes: 9

nicb
nicb

Reputation: 321

It's not pretty, but how about something like /^(1?\d{1,2}|2[0-4]\d|25[0-5])(\.(1?\d{1,2}|2[0-4]\d|25[0-5])){3}$/

Upvotes: 1

Related Questions