cppcoder
cppcoder

Reputation: 23095

Perl regular expression to match an IP address

I have written this code, but it does not work. Can someone point out the issue?

sub match_ip()
{
  my $ip = "The IP address is 216.108.225.236:60099";
  if($ip =~ /(\d{1-3}\.\d{1-3}\.\d{1-3}\.\d{1-3}\:\d{1-5})/)
  {
      print "$1\n";
  }
}

EDIT: I wanted to just extract the IP address, not do any validation.

Upvotes: 13

Views: 66107

Answers (12)

Dwayne
Dwayne

Reputation: 31

A shorter version of :

/((\d{1,3}\.){3}\d{1,3}\:\d{1,5})/

This expression is the same as the OPs except with 2 changes,

  1. The dash "-" becomes a comma, i.e. {1,3} and {1,5} , as other answers have indicated already,

  2. and my change is just shortening the expression by combining \d{1,3}\.\d{1,3}\.\d{1,3}\. into one .i.e. (\d{1,3}\.) with the {3} to match exactly 3 times

thanks @starball for the guidance ;)

Upvotes: 1

Devendra
Devendra

Reputation: 1

use strict;
use warnings;
open(FH,"<fileName.txt") or die "file not found ,$_";
while(my $line=<FH>)
{
push(my @arr,($line));
foreach my $arrVal (@arr)
{           
if($arrVal=~/IPv4 Address(?=.*\b((25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2  [0-4]\d|[0-1]?\d?\d)){3})\b)/)
{
print "$arrVal\n";
}
}

Upvotes: 0

Perlgrammer
Perlgrammer

Reputation: 1

Try this:

$variablename=~m/((((0-9)|((1-9)(0-9))|(1([0-9]){2})|(2[0-4][0-9])|(2[5][0-5]))\.){3})((0-9)|((1-9)(0-9))|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5]))/)

Upvotes: 0

Kumud Raj
Kumud Raj

Reputation: 11

#!/usr/bin/perl

$str = 'IP address is : 70.21.311.105';

    if ($str =~ m/(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/) {
        if ($1 <= 255 && $2 <= 255 && $3 <= 255 && $4 <= 255 ) {
            print "Valid $str\n";
    } else {
          print "invalid IP $str\n";
    }
}


__END__

Upvotes: 1

user2662353
user2662353

Reputation: 9

$ip = "10.255.256.1";

# will accept valid ips
if ($ip =~ m/^([1|2][0-9]{1,2})\.([0-255]{1,3}\.){2}[0-255]{1,3}/ && ($1 <=255)) {

  print "This is a valid ip: $ip \n";
 } else {
   print "This is not a valid ip: $ip \n";
}

Upvotes: -2

Tomas Jensen
Tomas Jensen

Reputation: 13

This might help:

my $ip = "195.249.61.14";

my @ips = (
    "set protocols bgp group IBGP-RRCL-CUSTOMER neighbor 195.249.61.142",
    "set protocols bgp group IBGP-RRCL-CUSTOMER neighbor 195.249.61.14",
    "set protocols bgp group IBGP-RRCL-CUSTOMER neighbor 195.249.61.141"
);

foreach (@ips) {
   print "$_\n" if ( /\b$ip\b/ );
}

Output:

set protocols bgp group IBGP-RRCL-CUSTOMER neighbor 195.249.61.14

Upvotes: 1

CowboyTim
CowboyTim

Reputation: 57

You can also use the following regex to make sure that the quad's aren't bigger then 255, it also "reuses" the digit matching instead of copypasting it 4 times.

my $rx = qr/^(?!(\.))(\.?(\d{1,3})(?(?{$^N > 255})(*FAIL))){4}$/;
if('192.168.1.2' =~ $rx){
  print "OK\n";
}

It uses a few features from perl regex matching (man perlre):

  • (*FAIL): stops pattern matching and fails
  • (?(condition)...): conditional match
  • (?{ code }): used within that condition

Upvotes: -1

Ashish Kumar
Ashish Kumar

Reputation: 851

Though there are well documented and tested modules at CPAN to match and validate IP addresses but there must be some solid reason for you not to use it. Personally I never had a real reason to use them for validation purpose either since I trusted/feeded the input.

Here is a shorter version of your regex, with it's own pitfalls:

while (my $ip = <DATA>)  {
    chomp $ip;
    # older version
    # if($ip =~ /(\d{1-3}\.\d{1-3}\.\d{1-3}\.\d{1-3}\:\d{1-5})/)

    # see below for explanation
    if ($ip =~ /\b(\d{1,3}(?:\.\d{1,3}){3}:\d{1,5})\b/)
    {
        print "$ip - matches\n";
    } else {
        print "$ip - does not match\n";
    }
}

__DATA__
216.108.225.236:60099
4.2.2.1:1
216.108.225.236:0
1216.1108.1225.1236:1234
216.108.225.236x:123
9216.108.225.236:8472
10.10.10.10

Results:

216.108.225.236:60099 - matches
4.2.2.1:1 - matches
216.108.225.236:0 - matches
1216.1108.1225.1236:1234 - does not match
216.108.225.236x:123 - does not match
9216.108.225.236:8472 - does not match
10.10.10.10 - does not match

Explanation:

/\b             # word boundary
(               # start memory capture group 1
\d{1,3}         # one to three digits, first octat
(:?             # start non memory capture group, notice ?:
  \.\d{1,3}     # a literal dot followed by an ip octet
)               # end non memory capture group
{3}             # three times of dots and ip octets
:               # match a colon
\d{1,5}         # port number, one to five digits
)               # end of memory capture group 1
\b              # word boundary

Hope this helps.

Upvotes: 2

Joel Berger
Joel Berger

Reputation: 20280

In the spirit of TIMTOWTDI here is another: the Regexp::Common::net portion of Regexp::Common may have regexen that you desire.

Upvotes: 7

Toto
Toto

Reputation: 91373

Change {1-3} to {1,3} same for {1-5} -> {1,5}

Upvotes: 15

user554546
user554546

Reputation:

Alternatively, you can use Data::Validate::IP, with the caveat that it won't recognize the port, so you'll have to split on :.

use strict;
use warnings;
use Data::Validate::IP;

my $ip_with_port="216.108.225.236:60099";
my $ip=(split /:/,$ip_with_port)[0];

my $validator=Data::Validate::IP->new;

if($validator->is_ipv4($ip))
{
  print "Yep, $ip is a valid IPv4 address.\n";
}
else
{
  print "Nope, $ip is not a valid IPv4 address.\n";
}

The output is:

Yep, 216.108.225.236 is a valid IPv4 address.

Upvotes: 4

jsf80238
jsf80238

Reputation: 107

Replace the dashes with commas.

/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d{1,5})/

Upvotes: 2

Related Questions