2011-08-17 77 views
4

为了成为一个更好的脚本编写者,有没有办法让下面的代码少用几行?perl高效代码

sub task1_2_2 { 
    #Make sure syslog configuration is correct 
    my @r3r = my @r4r = my @r5r = my @r6r = my @r7r = my @r8r = ("name = 67.176.10.200","facility-override = local3"); 
    my @r1r = ("name = 67.176.10.200","facility-override = local3","source-address = 67.176.255.1"); 
    my @r2r = ("name = 67.176.10.200","facility-override = local3","source-address = 67.176.255.2"); 
    my (@r1,@r2,@r3,@r4,@r5,@r6,@r7,@r8,%seen,@result1,@result2,@result3,@result4,@result5,@result6,@result7,@result8,$results,$item,$ii); 
    my $pass = "pass"; 
    my $xinfo = shift; 
    my $ip = shift; 
    my $data = XML::LibXML->load_xml(string => $xinfo); 
    my $datax = XML::LibXML::XPathContext->new($data); 
    my $syspath = '/configuration/system/syslog/host/*'; 
    foreach ($datax->findnodes($syspath)) { 
    if($ip eq "67.176.10.2" && $_->getName() ne "contents") {my $v = join " = ",$_->getName(),$_->to_literal;push @r1,$v}; 
    if($ip eq "67.176.10.3" && $_->getName() ne "contents") {my $v = join " = ",$_->getName(),$_->to_literal;push @r2,$v}; 
    if($ip eq "67.176.10.4" && $_->getName() ne "contents") {my $v = join " = ",$_->getName(),$_->to_literal;push @r3,$v}; 
    if($ip eq "67.176.10.5" && $_->getName() ne "contents") {my $v = join " = ",$_->getName(),$_->to_literal;push @r4,$v}; 
    if($ip eq "67.176.10.6" && $_->getName() ne "contents") {my $v = join " = ",$_->getName(),$_->to_literal;push @r5,$v}; 
    if($ip eq "67.176.10.7" && $_->getName() ne "contents") {my $v = join " = ",$_->getName(),$_->to_literal;push @r6,$v}; 
    if($ip eq "67.176.10.8" && $_->getName() ne "contents") {my $v = join " = ",$_->getName(),$_->to_literal;push @r7,$v}; 
    if($ip eq "67.176.10.9" && $_->getName() ne "contents") {my $v = join " = ",$_->getName(),$_->to_literal;push @r8,$v}; 
    } 
    @seen{@r1} = (); if($ip eq "67.176.10.2") {foreach $item (@r1r) { push(@result1, $item) unless exists $seen{$item}; }} 
    if(@result1) { 
       foreach $ii (@result1) {$results .= "On R1 Syslog $ii ,is either missing or incorrect configuration was done\n";} 
       } 
    %seen=(); 
    $item=$ii = undef; 
    @seen{@r2} = (); if($ip eq "67.176.10.3") {foreach $item (@r2r) { push(@result2, $item) unless exists $seen{$item}; }} 
    if(@result2) { 
       foreach $ii (@result2) {$results .= "On R2 Syslog $ii ,is either missing or incorrect configuration was done\n";} 
       } 
    %seen=(); 
    $item=$ii = undef; 
    @seen{@r3} = (); if($ip eq "67.176.10.4") {foreach $item (@r3r) { push(@result3, $item) unless exists $seen{$item}; }} 
    if(@result3) { 
       foreach $ii (@result3) {$results .= "On R3 Syslog $ii ,is either missing or incorrect configuration was done\n";} 
       } 
    %seen=(); 
    $item=$ii = undef; 
    @seen{@r4} = (); if($ip eq "67.176.10.5") {foreach $item (@r4r) { push(@result4, $item) unless exists $seen{$item}; }} 
    if(@result4) { 
       foreach $ii (@result4) {$results .= "On R4 Syslog $ii ,is either missing or incorrect configuration was done\n";} 
       } 
    %seen=(); 
    $item=$ii = undef; 
    @seen{@r5} = (); if($ip eq "67.176.10.6") {foreach $item (@r5r) { push(@result5, $item) unless exists $seen{$item}; }} 
    if(@result5) { 
       foreach $ii (@result5) {$results .= "On R5 Syslog $ii ,is either missing or incorrect configuration was done\n";} 
       } 
    %seen=(); 
    $item=$ii = undef; 
    @seen{@r6} = (); if($ip eq "67.176.10.7") {foreach $item (@r6r) { push(@result6, $item) unless exists $seen{$item}; }} 
    if(@result6) { 
       foreach $ii (@result6) {$results .= "On R6 Syslog $ii ,is either missing or incorrect configuration was done\n";} 
       } 
    %seen=(); 
    $item=$ii = undef; 
    @seen{@r7} = (); if($ip eq "67.176.10.8") {foreach $item (@r7r) { push(@result7, $item) unless exists $seen{$item}; }} 
    if(@result7) { 
       foreach $ii (@result7) {$results .= "On R7 Syslog $ii ,is either missing or incorrect configuration was done\n";} 
       } 
    %seen=(); 
    $item=$ii = undef; 
    @seen{@r8} = (); if($ip eq "67.176.10.9") {foreach $item (@r8r) { push(@result8, $item) unless exists $seen{$item}; }} 
    if(@result8) { 
       foreach $ii (@result8) {$results .= "On R8 Syslog $ii ,is either missing or incorrect configuration was done\n";} 
       } 
    if($results) { return $results; } elsif(!$results) { return $pass } 
} 

我将会写很多这些子程序。 基本上我通过一个路由器循环运行这个子程序,如果有什么东西不符合我的期望我想返回什么路由器是不正确的,缺少什么。代码的工作原理,但它感觉非常冗长,因为我没有编写很长的代码。 在此先感谢您的任何反馈意见。

回答

10

有很多需要改进的地方,我认为你最好是试着逐步改进它,测试它以确保它每次都能正常工作。

跳到我身上的东西最多的是重复使用硬编码的IP地址67.176.10.267.176.10.9。您将某些数据与其中的每个数据相关联(如@r1等)。因此,你会被建议考虑散列。

“但是等等,我只能把标量放在散列值中!”是的,所以你需要使用referencestutorial here)。

这里是你如何能简化第一大常规的例子:

sub task1_2_2 { 
    # ... 
    my %ip_address_to_r = (
     "67.176.10.2" => \@r1, 
     "67.176.10.3" => \@r2, 
     "67.176.10.4" => \@r3, 
     "67.176.10.5" => \@r4, 
     "67.176.10.6" => \@r5, 
     "67.176.10.7" => \@r6, 
     "67.176.10.8" => \@r7, 
     "67.176.10.9" => \@r8, 
); 

    # ... 

    foreach ($datax->findnodes($syspath)) { 
     next unless $_->getName() ne "contents"; # Go to next iteration of loop if we have "contents" 

     my $v = join(" = ", $_->getName(), $_->to_literal); 
     push @{$ip_address_to_r{$ip}}, $v; 
    } 

注意两件事情:

  1. 我们构造一个哈希IP地址引用数组关联(使用\参考运营商)。该引用将指向相同的数组,即使它与push操作一起更改。
  2. for循环的最后一行,我们检索引用作为标量(因为标量是引用)。然后我们使用@运算符“引用”引用,该运算符返回底层数组。然后push按照您的预期工作。

寻找方法使用关联数组和引用来获得优势。然后,您可以使用更少的代码行进行查找,并且在循环中不需要这么多的if语句。同时寻找在所有情况下都适用的常见条件,并将这些条件列入内部条件并将其置于循环的顶部。

+1

我知道引用是要走的路,只是以前从未使用过它们,并阅读了我没有上下文的文档,因此我无法用我的项目对其进行可视化。感谢您的解决方案,我会尽力回复。 – salparadise

+2

您可能会发现[perlreftut](http://perldoc.perl.org/perlreftut.html)更好的引用介绍。 –

+0

@格兰特麦克莱恩:谢谢,我忘了那一个:-( –