2014-10-09 47 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解釋器內運行的任何其他代碼 ,全局值$ /現在會被更改。

希望這會有所幫助。