繁体   English   中英

Perl怪异的Chomp和换行符

[英]Perl weird chomp and newline

从文件中提取行时出现奇怪的事情。

线路来自路由器发送的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接口又发生了什么?

问题是您正在处理来自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

我在您的代码中没有得到任何奇怪的东西,但是您在代码中的任何地方都没有使用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 

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

我怀疑您在读入文件的换行符末尾有这些字符之一。我还怀疑如果该行以\\ r \\ n结尾,单行压缩可能无法正常工作。

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

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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM