2014-10-09 71 views
0

编辑:改写为更清楚Perl的分裂停止在第一线

我遇到数据到一个名为RTR-shpolicymap_751257S0_126.xxx.xxx.xxx_OUTPUT文件的例子:

751257S0;126.xxx;FastEthernet0;up;up;not set;not set;; 
751257S0;126.xxx;BRI0;down;down;not set;not set;; 
751257S0;126.xxx;BRI0:1;down;down;not set;not set;; 
751257S0;126.xxx;BRI0:2;down;down;not set;not set;; 
751257S0;126.xxx;ATM0;up;up;not set;not set;; 
751257S0;126.xxx;ATM0.835;up;up;not set;not set;; 

Perl脚本执行SSH连接到路由器上,并建立连接时,它会调用该函数executeCommands 这里描述该功能:

sub executeCommands { 
    open(SSHCONFIG, "/tech/restools/scripts/mynet/RTR-ssh.conf"); 
    while (<SSHCONFIG>) { 
     @ligne = split(/;/, $_); 
     $listop = $ligne[0]; 
     $listcmd = $ligne[1]; 
     $fileprefix = $ligne[2]; 
     $parsername = $ligne[3]; 
     $parsername =~ s/\s+\z// ; 
     @cmd = split(/,/, $listcmd); 

     #Si l'operateur passe en parametre match l'operateur dans le fichier de config - execution des commandes 
     if ($listop =~ /$operateur/) { 
      for ($index = 0; $index <= $#cmd; $index++) { 
       $command = $cmd[$index]; 
       &changeCommand(\$command); 
       &sendCommand($command, $fileprefix); 
      } 
     } 
     else { 
      next; 
     } 

配置文件中包含此:

OBS,9 Cegetel,Altitude;sh policy-map $policyinterface;RTR-shpolicymap;RTR-parser9.pl 

现在,我在与功能的烦恼changeCommand

sub changeCommand { 
    my $arg1 = $_[0]; 
    if ($$arg1=~/^(.*)(\$policyinterface)(.*)/) { 
     print "recherche de l'interface contenant la policy voice correspondante... \n" ; 
     $fichier_parser1OUTPUT = `find $WORKINGDIR -type f -name RTR-shipint_\"*$codesite*$ip*OUTPUT\"` ; 
     @table_fichier_parser1OUTPUT = split(/\n/,$fichier_parser1OUTPUT); 
     for ($index4 = 0 ; $index4 <= $#table_fichier_parser1OUTPUT ; $index4++) { 
      $fichierNeeded = $table_fichier_parser1OUTPUT[$index4]; 
      open(DATA,$fichierNeeded) || die ("Erreur d'ouverture de $fichierNeeded\n"); 
      print "file $fichierNeeded have been opened \n"; 
      while (my $lineData=<DATA>) { 
       print "i am printing this line $lineData \n"; 
       my @lineSplitter = split(/;/, $lineData); 
       print "3e arg est <<$lineSplitter[2]>>\n"; 
      } 
     $command = "sh policy-map int " . $interfaceNeeded ; 
     } 
    } 
} 

这个问题是存在的,这是我”会发生什么m执行我的脚本:

recherche de l'interface contenant la policy voice correspondante... 
file /tech/restools/tmp/mynet/RTR-working-dir/RTR-shipint_751257S0_126.108.2.250_OUTPUT have been opened 
i am printing this line 751257S0;126.108.2.250;FastEthernet0;up;up;not set;not set;; 
3e arg est <<FastEthernet0>> 

Where是我的错误?是因为我以前的功能已经使用$ _

单独测试一个类似的脚本工作...

#!/usr/bin/perl 
use strict ; 

my $codesite="751257S0" ; 
my $ip = "126.xxx.xxx.xxx" ; 
my $WORKINGDIR="/tech/restools/tmp/mynet/RTR-working-dir"; 

my $fichier_parser1OUTPUT = `find $WORKINGDIR -type f -name RTR-shipint_\"*$codesite*$ip*OUTPUT\"` ; 
my @table_fichier_parser1OUTPUT = split(/\n/,$fichier_parser1OUTPUT); 
for (my $index4 = 0 ; $index4 <= $#table_fichier_parser1OUTPUT ; $index4++) { 
     my $fichierNeeded = $table_fichier_parser1OUTPUT[$index4]; 
     open(DATA,$fichierNeeded) || die ("Erreur d'ouverture de $fichierNeeded\n"); 
     print "file $fichierNeeded have been opened \n"; 
     while (my $lineData=<DATA>) { 
       print "i am printing this line $lineData \n"; 
       my @lineSplitter = split(/;/, $lineData); 
       print "3e arg est <<$lineSplitter[2]>>\n"; 
       } 
     } 

打印

i am printing this line 751257S0;126.108.2.250;FastEthernet0;up;up;not set;not set;; 

3e arg est <<FastEthernet0>> 
i am printing this line 751257S0;126.108.2.250;BRI0;down;down;not set;not set;; 

3e arg est <<BRI0>> 
i am printing this line 751257S0;126.108.2.250;BRI0:1;down;down;not set;not set;; 

3e arg est <<BRI0:1>> 
... 
+0

'print scalar @ table_fichier_parser1OUTPUT;'它只有1个元素吗? – toolic 2014-10-09 14:16:11

+0

是的,添加打印标量显示“1” – 2014-10-09 14:18:03

+1

你在Mac吗? – simbabque 2014-10-09 14:19:13

回答

1

鉴于文件fichier.1从问题的数据,下面的代码会产生什么似乎是效果你看到:

#!/usr/bin/env perl 
use strict; 
use warnings; 

local $/; 
my $fichierNeeded = "fichier.1"; 
open(DATA,$fichierNeeded) || die ("Erreur d'ouverture de $fichierNeeded\n"); 
print "Fichier $fichierNeeded est ouvert\n"; 
while (<DATA>) { 
    print "Ligne: $_"; 
    my @lineSplitter = split(/;/, $_); 
    print "3rd arg is <<$lineSplitter[2]>>\n"; 
} 

从这个输出是:

Fichier fichier.1 est ouvert 
Ligne: 751257S0;126.xxx;FastEthernet0;up;up;not set;not set;; 
751257S0;126.xxx;BRI0;down;down;not set;not set;; 
751257S0;126.xxx;BRI0:1;down;down;not set;not set;; 
751257S0;126.xxx;BRI0:2;down;down;not set;not set;; 
751257S0;126.xxx;ATM0;up;up;not set;not set;; 
751257S0;126.xxx;ATM0.835;up;up;not set;not set;; 
3rd arg is <<FastEthernet0>> 

如果省略了local $/;,输出为:

Fichier fichier.1 est ouvert 
Ligne: 751257S0;126.xxx;FastEthernet0;up;up;not set;not set;; 
3rd arg is <<FastEthernet0>> 
Ligne: 751257S0;126.xxx;BRI0;down;down;not set;not set;; 
3rd arg is <<BRI0>> 
Ligne: 751257S0;126.xxx;BRI0:1;down;down;not set;not set;; 
3rd arg is <<BRI0:1>> 
Ligne: 751257S0;126.xxx;BRI0:2;down;down;not set;not set;; 
3rd arg is <<BRI0:2>> 
Ligne: 751257S0;126.xxx;ATM0;up;up;not set;not set;; 
3rd arg is <<ATM0>> 
Ligne: 751257S0;126.xxx;ATM0.835;up;up;not set;not set;; 
3rd arg is <<ATM0.835>> 

既然你不给我们所代码可用片段(循环是不完整的,甚至是)和你的代码不必要使我们在目录等上执行find命令,我们无法很好地复制您的环境。

正如我在评论中指出的那样,您需要了解如何创建MCVE(Minimal, Complete, Verifiable Example)或SSCCE(Short, Self-Contained, Correct Example)。这是两个名称(和两个描述)相同的基本思想。我提供的代码接近成为MCVE或SSCCE(除非不清楚它是否重现了您的问题)。

还要注意一些基本的调试技巧。打印刚刚阅读的数据是发现问题最基本的方法。在第一个示例输出中,整个文件立即被写入内存。如果$/的设置对您的代码隐藏(某人在您调用的子例程中不小心),这可能是非常宝贵的。我还划分了匹配的字段(将它们括在双尖括号中),这样如果数据中有奇怪的字符,我可以更容易地看到它们。如果你不确定发生了什么,你应该做的第一件事是添加一些打印语句来打印你正在处理的内容。

+0

这段代码是一个非常大的脚本的一部分,bash用args调用perl,试图通过SSH连接到设备,写下类似“sh ip int brief”的文件命令... 当我添加“local $ /“语句,它打印你所期望的。 这是什么意思?我已经在上面的“if”语句中使用“$ _”,就在此代码之前。 – 2014-10-10 06:29:47

+0

这是否意味着“while()将文件读取为一行而不是多行?” – 2014-10-10 06:37:11

+0

这个问题已经被修改了很多......一个假设是'while()'命令将文件读为一个而不是多行,另一个是该文件只有一行,尽管你不这么认为,所显示的代码没有使用分割名称,所以你为什么关心它?如果在循环中有一个函数调用,那么也许该函数使用''句柄,这会导致循环结束。考虑更广泛地使用“我的” - “严格使用;使用警告;'好!使用词法文件句柄:'打开我的$ fh,'<',$ fichier或die'。 – 2014-10-10 13:55:34

1

乔纳森的回答继

下面是perldoc perlvar相关的部分,讨论什么可以在程序中发生

在要 本地化这些变量[如$大多数情况下/ ],因为如果你不这样做, 更改可能会影响依赖于您更改的特殊变量的默认值的其他模块。这是正确的 方法来读取整个文件一次一个:

 open my $fh, "<", "foo" or die $!; 
     local $/; # enable localized slurp mode 
     my $content = <$fh>; 
     close $fh; 

但是,下面的代码是相当糟糕:

 open my $fh, "<", "foo" or die $!; 
     undef $/; # enable slurp mode 
     my $content = <$fh>; 
     close $fh; 

,因为一些其他的模块,可能需要阅读一些数据文件 默认为“行模式”,所以如果我们刚才介绍的代码已经执行了 ,那么对于在同一个Perl解释器内运行的任何其他代码 ,全局值$ /现在会被更改。

希望这会有所帮助。