如何解析所选输出的配置文件?

时间:2019-02-27 16:40:49

标签: python perl parsing

我的主目录(linux)中有一个文本配置文件。格式如下:

ip nat pool nat_pool1 192.168.10.100 192.168.10.100 netmask /24
!
ip route 0.0.0.0 /0 192.168.15.1
!
slb server websrv1 192.168.10.5
  port 80 tcp
!
slb server websrv2 192.168.10.6
  port 80 tcp
!
slb server websrv3 192.168.10.7
  port 80 tcp
!
slb service-group websrv_80 tcp
  member websrv1 80
  member websrv2 80
  member websrv3 80
!
slb virtual-server websrv1 192.168.15.11
  port 80 tcp
    source-nat pool at_pool1
    service-group websrv_80
!
end

我需要一个脚本(perl?/ python?),该脚本可以被提供这样的参数:

脚本名称虚拟服务器名称

然后生成显示绑定到虚拟服务器的source-nat和service-group详细信息的输出。因此,在下面的示例配置中,如果已运行 “ script_name websrv1”

该脚本将解析websrv1虚拟服务器,并显示输出以及与之绑定的source-nat和slb-service-group配置信息。该脚本将输出如下内容:

slb virtual-server websrv1 192.168.15.11
  port 80 tcp
    source-nat pool at_pool1
    service-group websrv_80

slb service-group websrv_80 tcp  
  member websrv1 80  
  member websrv2 80  
  member websrv3 80  

ip nat pool nat_pool1 192.168.10.100 192.168.10.100 netmask /24

如果在其下面还添加了websrv1、2和3行,将是一个额外的好处。非常感谢您的帮助。

4 个答案:

答案 0 :(得分:0)

在配置文件的结构中,脚本首先需要进行节检测。以下是我在Perl中的首次尝试:

  • STDIN读取行
  • 标量上下文中的
  • range运算符,即作为触发器,用于检测节的开始和结束
  • 在本节中
    • 解析起始行以检测类型
    • 解析其他行
    • 根据节类型的加工线
use strict;
use warnings;

while (<STDIN>) {
    chomp;

    if (/^slb\s+/../^!\s*$/) {
        #print "SECTION: $_\n";
        my($type, $remainder);

        # start line
        if      (($type, $remainder) = /^slb\s+(\S+)\s+(.+)/) {
            print "SECTION ${type} START (${remainder})\n";

        # other lines in section
        } elsif (($type, $remainder) = /^\s+(\S+)\s+(.+)/) {
            print "OTHER ${type} LINE (${remainder})\n";

        # end line, i.e. "!"
        } else {
            #print "END LINE: $_\n";
        }
    }
}
exit 0;

以您的示例进行测试:

$ perl dummy.pl <dummy.txt
SECTION server START (websrv1 192.168.10.5)
OTHER port LINE (80 tcp)
SECTION server START (websrv2 192.168.10.6)
OTHER port LINE (80 tcp)
SECTION server START (websrv3 192.168.10.7)
OTHER port LINE (80 tcp)
SECTION service-group START (websrv_80 tcp)
OTHER member LINE (websrv1 80)
OTHER member LINE (websrv2 80)
OTHER member LINE (websrv3 80)
SECTION virtual-server START (websrv1 192.168.15.11)
OTHER port LINE (80 tcp)
OTHER source-nat LINE (pool at_pool1)
OTHER service-group LINE (websrv_80)

替代:,因为您的脚本需要将语义含义附加到解析的内容上,并在不同类型的“对象”(虚拟,服务器,组等)之间建立连接,因此您应该研究一下为您的配置文件语法编写一个真正的词法分析器/解析器。最终,这将比手工解析这些行乏味。

答案 1 :(得分:0)

这可以通过相对简单的awk脚本(从this stackoverflow post.

修改)来完成
awk '/websrv1/{flag=1}/!/{flag=0;}flag' config-file.conf 

将websrv1替换为您感兴趣的搜索词,并用config-file.conf替换要搜索的文件。

答案 2 :(得分:0)

Sinc,您没有付出任何努力,但会感谢您的帮助,以下是一些让您开始使用perl的东西:

您是否有机会知道

if (cond .. cond) {
}

这可以在while循环中使用,例如:

while (<>) {
    if (/^slb/ .. /^(!|END)/) {
      ... here you can collect your slb-blocks into a hash
    }
}

如果您已将数据读入哈希中,例如:

'slb service-group websrv_80 tcp' => "  member websrv1 80\n  member websrv2 80\n  member websrv3 80",
'slb virtual-server websrv1 192.168.15.11' => "  port 80 tcp\n    source-nat pool at_pool1\n    service-group websrv_80"

我认为遍历哈希键,打印出值很容易。然后,您可以自动地分析输出中是否有任何其他要打印的数据。

答案 3 :(得分:0)

以下是如何使用Regexp::Grammars的示例:

use strict;
use warnings;
use Regexp::Grammars;

my $parser = qr{   
          <nocontext:>
          <blocks>
          <rule: blocks> (?: <[block]><.block_separator>)*
          <rule: block> <[line]>+
          <token: line> ^(?: $ | (?: (?!(?:end | !))(?: .*?$)))\n?
          <token: block_separator> ^(?: end | !)\s*\n?
}mx;

my $fn = 'config.txt';
open ( my $fh, '<', $fn ) or die "Could not open file '$fn': $!";
my $text = do { local $/; <$fh> };
close $fh;

if ($text =~ $parser) {
    for my $block (@{ $/{blocks}{block} }) {
        print join '', @{ $block->{line} };
        print "\n", '-' x 40, "\n";
    }
}

输出

ip nat pool nat_pool1 192.168.10.100 192.168.10.100 netmask /24

----------------------------------------
ip route 0.0.0.0 /0 192.168.15.1

----------------------------------------
slb server websrv1 192.168.10.5
  port 80 tcp

----------------------------------------
slb server websrv2 192.168.10.6
  port 80 tcp

----------------------------------------
slb server websrv3 192.168.10.7
  port 80 tcp

----------------------------------------
slb service-group websrv_80 tcp
  member websrv1 80
  member websrv2 80
  member websrv3 80

----------------------------------------
slb virtual-server websrv1 192.168.15.11
  port 80 tcp
    source-nat pool at_pool1
    service-group websrv_80

----------------------------------------