1

My target is to replace only the three first digits in IP address with new IP address For example

 NEW three first three digits – 17.100.10
 OLD three first three digits - 12.200.10 
 Existing IP address in file  - 12.200.10.2 

Then I will get the new IP as 17.100.10.2

So I write the following Perl command in order to perform the replace action

But the problem is that if the NEW IP matches the three last digits then it will replace them also

So

What need to change in my Perl command in order to replace only the three first digits in IP address?

Real Example1 that described the problem:

export OLD_IP=192.9.1
export NEW_IP=172.192.9

.

echo 1.192.9.1 | perl -i -pe 'next if /^ *#/; s/(\b|\D)$ENV{OLD_IP}(\b|\D)/$1$ENV      {NEW_IP}$2/g'  
 1.172.192.9

.

4

3 回答 3

4
#!/bin/perl

my @ip = split('\.', $old_ip);
$ip[0] = 172;
$ip[1] = 16;
$ip[2] = 0;
$new_ip = join(".", @ip);

OR

#!/bin/perl

my @ip = split('\.', $old_ip);
$new_ip = '172.16.0.' . $ip[3];

OR

s/(\d{1,3}\.){3}(?=(\d+$))/$ENV{new_ip}/

For the single line, WTF, version; that should drop into your shell script...

# export new_ip=172.168.0.
# echo 192.168.5.6 | perl -i pe 's/(\d{1,3}\.){3}(?=(\d+$))/$ENV{new_ip}/'
172.16.0.6
于 2012-12-26T13:44:39.520 回答
3

这只是您的代码存在的三个问题之一。另外两个是:

  • 您的代码192.9.100.1(OLD_IP=192.9.1)更改为172.192.900.1(NEW_IP=172.192.9)。

  • 您的代码192.101.1.2(OLD_IP=192.1.1)更改为172.192.9.1.2(NEW_IP=172.192.9)。

解决方案:

perl -pe's/(?<![\d.])\Q$ENV{OLD_IP}\E(?=\.\d)/$ENV{NEW_IP}/g'

笔记:

  • ^会比(?<![\d.])IP 地址总是在一行的开头更好。(这/g将变得无用。)
  • (?<!\S)(?<![\d.])如果 IP 地址总是以空格、制表符开头或总是在行首找到,那会更好。
于 2012-12-27T00:12:00.523 回答
0

如果每个 IP 地址都出现在自己的一行中,这很容易:

s/^\Q$ENV{OLD_IP}\E/$ENV{NEW_IP}/mg

如果没有,您可以使用否定的lookbehind断言:

s/(?<![\d.])\Q$ENV{OLD_IP}\E/$ENV{NEW_IP}/g

这将匹配并替换 中给出的字符串OLD_IP,除非它跟在数字或句点之后。

编辑:要解决 ikegami 指出的问题,您还应该确保匹配的字符串后面没有数字:

s/(?<![\d.])\Q$ENV{OLD_IP}\E(?!\d)/$ENV{NEW_IP}/g

与 ikegami 的解决方案不同,这适用于任意数量的八位字节,而不仅仅是三个或更少。

于 2012-12-27T00:13:58.027 回答