[英]Perl weird chomp and newline
I'm having weird things when extracting line from file. 从文件中提取行时出现奇怪的事情。
Lines are coming from SSH commands sent on a router and saved into a file. 线路来自路由器发送的SSH命令,并保存到文件中。 They are looking like : saved_commands
它们看起来像: 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
So, in my PERL script, when i'm reading this file, I make this : 因此,在我的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);
The output should be : 输出应为:
FastEthernet0 ; upup ; not set
FastEthernet1 ; upup ; not set
FastEthernet2 ; updown ; not set
But unfortunately, the output is more like : 但是不幸的是,输出更像是:
FastEthernet0 ; upup
; not set
FastEthernet1 ; upup
; not set
FastEthernet2 ; updown
; not set
I guess there's a newline somewhere, probably at the end of each interface line. 我猜可能在每个界面行的末尾都有换行符。 But i tried several things, like
chomp($_)
, or even 但是我尝试了几件事,例如
chomp($_)
,甚至
$_ =~ s/
//;
But things get weirder. 但是事情变得奇怪了。 EDIT : I tried other answers, having same issue.
编辑:我尝试了其他答案,有同样的问题。 Using Borodin's answer :
使用鲍罗丁的答案:
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);
The output is like 输出就像
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
We are getting closer to it, what happened to the others FastEthernet interfaces ? 我们越来越接近它,其他FastEthernet接口又发生了什么?
The problem is that you are processing a file from a Windows system that has CRLF at the end of each line instead of just LF (newline). 问题是您正在处理来自Windows系统的文件,该文件的每行末尾都有CRLF,而不仅仅是LF(换行符)。
chomp
removes the newline, but the carriage-return remains and messes up your output. chomp
删除了换行符,但是回车符仍然保留并且使您的输出混乱。 You can get around this by using s/\\s+\\z//
instead of chomp
. 您可以使用
s/\\s+\\z//
代替chomp
。
But you can avoid the problem with line terminators altogether by using split
with a single space string (not a regex). 但是,您可以通过对单个空格字符串 (而不是正则表达式)使用
split
来完全避免行终止符的问题。 That is the default if you don't pass any parameters at all, and it splits on any combination of whitespace (which includes newlines and carriage-returns), ignoring any leading spaces. 如果您根本不传递任何参数,那么它将是默认值,它将在空白的任何组合(包括换行符和回车符)上分割,而忽略任何前导空格。
This program seems to do what you want. 该程序似乎可以满足您的要求。 It makes use of regular expressions instead of
split
to get straight to the correct part of the data without using temporary arrays. 它使用正则表达式而不是
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 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
output 输出
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
I am not getting anything weird in your code but you are not using chomp anywhere in the code. 我在您的代码中没有得到任何奇怪的东西,但是您在代码中的任何地方都没有使用chomp。
Just add chomp $_;
只需添加
chomp $_;
at the very start of your while loop. 在您的while循环开始时。
Try this Code: 试试这个代码:
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
and this is the output: 这是输出:
FastEthernet0 ; upup ; not set
FastEthernet1 ; upup ; not set
FastEthernet2 ; updown ; not set
Try this $etat =~ s/[\\n]+$//; 试试这个$ etat =〜s / [\\ n] + $ //; or if that fails $etat =~ s/[\\r\\n]+$//;
或如果失败$ etat =〜s / [\\ r \\ n] + $ //;
I suspect you have one of these as the end of your newlines in the file being read in. I also suspect a single chomp may not work if the line ends in \\r\\n. 我怀疑您在读入文件的换行符末尾有这些字符之一。我还怀疑如果该行以\\ r \\ n结尾,单行压缩可能无法正常工作。
Without knowing the actual input file exact details the below is a suggestion and is written based on the contents of the input file you have provided in your post. 不知道实际输入文件的确切详细信息,以下是建议,是根据您在帖子中提供的输入文件的内容编写的。
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.