如何使用Perl单线程基于第一线模式匹配添加线?

时间:2015-01-19 23:34:46

标签: regex perl in-place

我的老板需要通过添加以下行来更改几十(数百)台主机上的特定路由文件:

10.11.0.0/16   via 172.16.2.XX dev tun0

...其中XX基于" dev"之前的八位字节。关键字在同一文件的第一行。

他希望它成为一个自动就地编辑。现有文件的第一行如下所示:

10.12.123.0/22 via 172.16.2.24 dev tun0
10.13.234.0/23 via 172.16.2.22 dev tun0

所以结果应该是这样的:

10.12.123.0/22 via 172.16.2.24 dev tun0
10.13.234.0/23 via 172.16.2.22 dev tun0
10.11.0.0/16   via 172.16.2.24 dev tun0

...简单地添加了最后一行,并且从第一行的最后一个八位字节复制了该行中的最后一个八位字节。

3 个答案:

答案 0 :(得分:1)

当然,你可以将它塞进一个班轮,但为什么惩罚自己(和那个必须在路上保持这种情况的可怜的草皮)。 -i之类的东西在程序中起作用。这是您正在寻找的基本模式。

#!/usr/bin/env perl -n -i

print $_;
if( /...whatever you want to match.../ ) {
    print "...whatever extra line you want to add...";
}

-n表示逐行迭代,好像在程序周围有一个while循环。与-p不同,它不会自动打印该行。当然,你可以附加到$_,但这可以让我们更好地控制。

-i表示要编辑文件,而不是只打印到STDOUT。

答案 1 :(得分:1)

您似乎没有为每个输入文件重置行计数器$.,而close(ARGV)就是这样做了,

perl -i.bak -pe'
  $octet = $1 if /(\d+)\s+dev/ and $. ==1;
  $_ .= "10.11.0.0/16 via 172.16.2.$octet dev tun0\n", close(ARGV) if eof;
' "$filenames"

答案 2 :(得分:0)

这是我的尝试......对于单个文件似乎有效

perl -pi.bak -e '$octet = $1 if /(\d+)\s+dev/ and $. == 1;\
  $line="10.11.0.0/16 via 172.16.2.$octet dev tun0\n";\
  $_ = $_ . $line if eof;' "$filenames"

这是一个更安全的变体,只会在每个文件的第一行找到匹配的模式后附加预期的行 。 (它还会重置$。如Сухой27所述):

perl -pi.bak -e '$line ="10.11.0.0/16 via 172.16.2.$1 dev tun0\n"\
  if /(\d+)\s+dev/ && $. == 1;\
  close(ARGV), $_ = $_ . $line if eof;' "$filenames"

(如果找不到正则表达式的匹配项,则$ line为空,并且向$ _追加空字符串是无害的)。