Performing a regex substitution Perl

2019-03-04 09:35发布

问题:

Assuming I have the IP 10.23.233.34 I would like to simply swap the 233 for 234. The first, second, and last octet are unknown. The third octet is either 233 or 234. I want to do the substitution such that it matches the IP, subs, and keeps everything else while still switching the last octet. For example:

Input: 10.23.233.34

s/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){}233\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){}234\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/

Output: 10.23.234.34

回答1:

This problem really isn't suited well for a regex solution. Instead, I would do something like the following:

$in = "10.23.233.34";
@a = split /\./, $in;
if ($a[2] == '233') {
    $a[2] = '234';
}
print join(".", @a);

The above code is far more readable than any regex you might come up with. Furthermore, the next person who has to maintain your code will be able to actually read it.



回答2:

Sometimes regexes make things brittle and harder to understand. Nonetheless:

my $ip = '10.23.233.34';
...
for ($ip) {
    s!(?<=\.)233(?=\.\d+$)!234!;
}

Details: If given a well-formed dotted quad, the above looks for '233' in what must be the third octet: preceded by a dot and followed by a dot, then one or more digits, then end-of-string. The ?<= and ?= prevent anything other than the '233' from being captured, and then '234' is substituted. This approach does not validate that the IP address is well-formed.



回答3:

$byte = qr/(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])/;
s/($byte)\.($byte)\.(23[34])\.($byte)/join '.', $1, $2, 467-$3, $4/e;


回答4:

Here's an option:

use strict;
use warnings;

my $ip = '10.23.233.34';

$ip =~ s/(\d+)(\.\d+)$/($1 == 233 ? $1+1 : $1) . $2/e;

print $ip;

Output:

10.23.234.34