0

从文件中提取行时我遇到了奇怪的事情。

行来自在路由器上发送并保存到文件中的 SSH 命令。它们看起来像: saved_commands

    FastEthernet0 is up, line protocol is up
    Helper address is not set
    FastEthernet1 is up, line protocol is up
    Helper address is not set
    FastEthernet2 is up, line protocol is down
    Helper address is not set

所以,在我的 PERL 脚本中,当我阅读这个文件时,我会这样做:

while (<LIRE>) {
    $ifname = "";
    $etat = "";
    $myip = "";
    if (/line protocol/) {
        @status = split(/,/, $_) ;
        @interface = split(/ /, $_);
        $ifname = $interface[0];
        for ($index = 0; $index <= $#status; $index++) {
            @etat_par_if = split(/ /, $status[$index]);
            $etat .= pop(@etat_par_if);
        }
    }
    if (/Helper|helper/) {
        @helper = split(/ /, $_) ;
        $myip = pop(@helper);
        if ($myip =~ /126/) {

        }
        else {
            $myip = "not set";
        }
    }
    if ($myip eq ""){
        $myip = "not set";
    }       
    if ($ifname ne ""){
    print "$ifname ; $etat ; $myip \n";
    }
}
close(LIRE);

输出应该是:

FastEthernet0 ; upup ; not set
FastEthernet1 ; upup ; not set
FastEthernet2 ; updown ; not set

但不幸的是,输出更像:

FastEthernet0 ; upup
 ; not set
FastEthernet1 ; upup
 ; not set
FastEthernet2 ; updown
 ; not set

我猜某处有一个换行符,可能在每个接口行的末尾。但我尝试了几件事,比如chomp($_),甚至

$_ =~ s/
//;

但事情变得更奇怪了。编辑:我尝试了其他答案,也有同样的问题。 使用鲍罗丁的回答:

my ($etat, $ifname, $myip);

open(DATA,$fichier) || die ("Erreur d'ouverture de $fichier\n") ;
while (<DATA>) {

    if (/line protocol/) {
        $ifname = (split)[0];
        my @status    = split /,/;
        for (@status) {
          $etat .= (split)[-1];
        }
    }
    elsif (/helper/i) {
        my @helper = split;
        $myip = (split)[-1];
        $myip = 'not set' unless $myip =~ /\d/;
    }

    if ($ifname and $myip) {
      print "$ifname ; $etat ; $myip\n";
      $etat = $ifname = $myip = undef;
    }

}
close(DATA);

输出就像

FastEthernet0 ; upup ; not set
Vlan1 ; downdowndowndowndowndownupupupdownupdownupdownupdownupdownupdownupdownupup ; 126.0.24.130
Loopback0 ; upup ; not set
Loopback1 ; upup ; not set
Tunnel100 ; upupupupupup ; not set
Dialer1 ; upup ; not set
Tunnel101 ; upup ; not set
Tunnel200 ; upup ; not set
Tunnel201 ; upup ; not set
Tunnel300 ; upup ; not set

我们越来越接近它,其他 FastEthernet 接口发生了什么?

4

4 回答 4

1

问题是您正在处理来自 Windows 系统的文件,该文件在每行末尾都有 CRLF,而不仅仅是 LF(换行符)。chomp删除换行符,但回车符仍然存在并弄乱了您的输出。您可以通过使用s/\s+\z//而不是来解决此问题chomp

split但是您可以通过使用单个空格字符串(不是正则表达式)来完全避免行终止符的问题。如果您根本不传递任何参数,这是默认设置,它会根据空格的任何组合(包括换行符和回车符)拆分,忽略任何前导空格。

这个程序似乎做你想做的事。它使用正则表达式而不是split直接获取数据的正确部分而不使用临时数组。

use strict;
use warnings;

my $fichier = 'fichier.txt';

open my $lire, '<', $fichier or die "Erreur d'ouverture de $fichier: $!";

my ($ifname, $etat, $myip);

while (<$lire>) {

   if (/line protocol/) {

      if ($ifname) {
         printf "%s ; %s ; %s\n", $ifname, $etat, $myip // 'not set';
         $myip = undef;
      }

      ($ifname) = /(\S+)/;
      $etat = join '', /(\S+)\s*(?:,|\z)/g;
   }
   elsif (/helper.*\s([\d.]+)/i) {
      $myip = $1;
   }

}

if ($ifname) {
   printf "%s ; %s ; %s\n", $ifname, $etat, $myip // 'not set';
}

fichier.txt

FastEthernet0 is up, line protocol is up
Helper address is not set
FastEthernet1 is up, line protocol is up
Helper address is not set
FastEthernet2 is up, line protocol is down
Helper address is 126.0.24.130
FastEthernet3 is up, line protocol is down
FastEthernet4 is up, line protocol is down
Helper address is 126.0.24.128
FastEthernet5 is up, line protocol is down

输出

FastEthernet0 ; upup ; not set
FastEthernet1 ; upup ; not set
FastEthernet2 ; updown ; 126.0.24.130
FastEthernet3 ; updown ; not set
FastEthernet4 ; updown ; 126.0.24.128
FastEthernet5 ; updown ; not set
于 2014-07-31T10:26:23.650 回答
0

我在您的代码中没有发现任何奇怪的东西,但是您没有在代码中的任何地方使用 chomp 。

只需chomp $_;在 while 循环的最开始添加即可。

试试这个代码:

while (<DATA>) {
    chomp;
    $ifname = "";
    $etat = "";
    $myip = "";
    if (/line protocol/) {
        @status = split(/,/, $_) ;
        @interface = split(/ /, $_);
        $ifname = $interface[0];
        for ($index = 0; $index <= $#status; $index++) {
            @etat_par_if = split(/ /, $status[$index]);
            #chomp @etat_par_if;
            $etat .= pop(@etat_par_if);
        }
    }
    if (/Helper|helper/) {
        @helper = split(/ /, $_) ;
        $myip = pop(@helper);
        if ($myip =~ /126/) {

        }
        else {
            $myip = "not set";
        }
    }
    if ($myip eq ""){
        $myip = "not set";
    }       
    if ($ifname ne ""){
    print "$ifname ; $etat ; $myip \n";
    }
}
close(DATA);


__DATA__
FastEthernet0 is up, line protocol is up
Helper address is not set
FastEthernet1 is up, line protocol is up
Helper address is not set
FastEthernet2 is up, line protocol is down
Helper address is not set

这是输出:

FastEthernet0 ; upup ; not set 
FastEthernet1 ; upup ; not set 
FastEthernet2 ; updown ; not set 
于 2014-07-31T09:23:57.713 回答
0

试试这个 $etat =~ s/[\n]+$//; 或者如果失败 $etat =~ s/[\r\n]+$//;

我怀疑您将其中一个作为正在读入的文件中换行符的结尾。我还怀疑如果该行以 \r\n 结尾,则单个 chomp 可能不起作用。

于 2014-07-31T09:56:16.077 回答
-1

在不知道实际输入文件的确切细节的情况下,以下是一个建议,是根据您在帖子中提供的输入文件的内容编写的。

use strict;
use warnings;

open (my $file, '<', 'LIRE.txt') or die "unable to open file : $!\n";
while (<$file>) {
        chomp();
        if (/line protocol/){
                my ($ifname) = /^([A-Za-z0-9]+)\s/;
                my @status = map { /\s([A-Za-z]+)$/ } split(',');
                print "$ifname ; ", @status;
        } elsif (/[Hh]elper/){
                my $ip = /\s(\w+)$/;
                print " ; ", $ip =~ /126/ ? $ip : "not set", "\n";
        }
}
close($file);
于 2014-07-31T09:51:19.187 回答