Perl奇怪的chomp和换行

时间:2014-07-31 09:08:13

标签: perl printing pop chomp

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

行来自路由器上发送的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/
//;

但事情变得更加怪异。 编辑: 我尝试了其他答案,遇到同样的问题。 使用Borodin的回答:

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 个答案:

答案 0 :(得分:1)

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

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

这个程序似乎做你想要的。它使用正则表达式而不是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

答案 1 :(得分:0)

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

只需在while循环开始时添加chomp $_;

试用此代码:

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 

答案 2 :(得分:0)

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

我怀疑你将其中一个作为读取文件中换行符的结尾。我还怀疑如果行以\ r \ n结束,单个chomp可能无法工作。

答案 3 :(得分:-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);