如何在下一行解析包含相关数据的数组
打开我的 $outfile、'>'、$outpath 或 $logger->logdie("Error: Can't open $outpath. It may be open.:$!");我有一个命令,其输出被读入一个数组(按换行符分割),然后进行解析。 当我过去从文件中获取它并仅使用本地 $/ = ""; 时,它工作得非常完美。但我读到拥有中间文件是浪费,并更改了它。现在我根本无法阅读下一行! 以下是需要解析的不同类型的数据输出:
fcalias name DA540_MAE_I0032 vsan 24
pwwn X0:00:00:63:ab:03:86:e1
fcalias name NAEMS02_DH6_AUX0 vsan 53
fcalias name NRTMF02_DM3_BE0 vsan 53
fcalias name DMSRT56-777_09C0 vsan 53
interface fc2/33 swwn 20:13:ev:0d:ed:3e:da:00
当 pwwn 出现时,我希望将其添加到 fcalias 中,变量“type”= pwwn/swwn/none 取决于数据。
这是我的代码,
sub fcalias
{ my ($path, $commandfile, $switch_ip, @data) = @_;
my $outpath = "$path${switch_ip}_${commandfile}.csv";
open my $outfile, '>', $outpath or $logger->logdie("Error: Can't open $outpath. It may be open.:$!");
my ($type, $fcalias, $vsan);
while (@data)
{ $_ = shift(@data);
s/^\s+//; # Delete leading whitespaces
next if (/^$/); # Skip empty lines
if (/^fcalias name (\S+) vsan (\S+)/)
{($fcalias, $vsan) = ($1, $2);next;}
elsif (/^pwwn (\S+)/)
{$type = "pwwn"; my $pwwn = $1;
print ($outfile, "$fcalias;$vsan;$type;$pwwn;;;$switch_ip\n");
}
elsif (/interface (\S+) swwn (\S+)/)
{$type = "interface";
my ($interface,$swwn) = ($1,$2);
print ($outfile, "$fcalias;$vsan;$type;;$swwn;$interface;$switch_ip\n");
}
else {$type = "none";
print ($outfile, "$fcalias;$vsan;$type;;;;$switch_ip\n");
# print "$_ \n";
}
}
print "..................DONE\n";
}
当然,正如您可能已经注意到的那样,其他根本不起作用,我得到了 fcalias 双打。但无论我尝试什么,我都无法添加获得我需要的输出。这个子例程是一个更大的脚本的一部分,该脚本已经过优化,只是缺少这一部分......帮助!
作为参考,这是旧的代码循环。请原谅冗长的帖子和代码格式。我试过。谢谢!
local $/ = "";
while (<DATA>)
{ if ($_ =~ m/^fcalias name (\S+) vsan (\S+)\s+pwwn (\S+)/)
{ my ($fcalias, $vsan, $pwwn) = ($1, $2, $3);
my $type = "pwwn";
print (OUTFILE "$fcalias;$vsan;$type;$pwwn;;;$switch_ip\n");
}
elsif ($_ =~ m/^fcalias name (\S+) vsan (\S+)\s+interface (\S+) swwn (\S+)/)
{ my ($fcalias, $vsan, $interface, $swwn) = ($1, $2, $3 ,$4);
my $type = "interface";
print (OUTFILE "$fcalias;$vsan;$type;;$interface;$swwn;$switch_ip\n");
}
else ($_ =~ m/^fcalias name (\S+) vsan (\S+)/)
{ my ($fcalias, $vsan) = ($1, $2);
my $type = "none";
print (OUTFILE "$fcalias;$vsan;$type;;;;$switch_ip\n");
}
}
open my $outfile, '>', $outpath or $logger->logdie("Error: Can't open $outpath. It may be open.:$!");I have a command whose output is read into an array (split by newline) and then parsed.
It worked perfectly when I used to slurp it from a file and just use local $/ = "";. but I read that having an intermediary file is wasteful, and changed it. now I can't read the next line at all!!!
here are the different types of data output needing to be parsed:
fcalias name DA540_MAE_I0032 vsan 24
pwwn X0:00:00:63:ab:03:86:e1
fcalias name NAEMS02_DH6_AUX0 vsan 53
fcalias name NRTMF02_DM3_BE0 vsan 53
fcalias name DMSRT56-777_09C0 vsan 53
interface fc2/33 swwn 20:13:ev:0d:ed:3e:da:00
when pwwn appears, I want it added to the fcalias, with variable "type" = pwwn/swwn/none depending on the data.
here's my code,
sub fcalias
{ my ($path, $commandfile, $switch_ip, @data) = @_;
my $outpath = "$path${switch_ip}_${commandfile}.csv";
open my $outfile, '>', $outpath or $logger->logdie("Error: Can't open $outpath. It may be open.:$!");
my ($type, $fcalias, $vsan);
while (@data)
{ $_ = shift(@data);
s/^\s+//; # Delete leading whitespaces
next if (/^$/); # Skip empty lines
if (/^fcalias name (\S+) vsan (\S+)/)
{($fcalias, $vsan) = ($1, $2);next;}
elsif (/^pwwn (\S+)/)
{$type = "pwwn"; my $pwwn = $1;
print ($outfile, "$fcalias;$vsan;$type;$pwwn;;;$switch_ip\n");
}
elsif (/interface (\S+) swwn (\S+)/)
{$type = "interface";
my ($interface,$swwn) = ($1,$2);
print ($outfile, "$fcalias;$vsan;$type;;$swwn;$interface;$switch_ip\n");
}
else {$type = "none";
print ($outfile, "$fcalias;$vsan;$type;;;;$switch_ip\n");
# print "$_ \n";
}
}
print "..................DONE\n";
}
of course as you might have noticed, the else doesnt work at all, I get fcalias doubles. but no matter what I try, I can't add get the output I need. This subroutine is part of a bigger script which has been optimized and is just missing this part.....Help!
for reference, here's the old code loop. please excuse the long post and code formatting. I tried. Thanks!
local $/ = "";
while (<DATA>)
{ if ($_ =~ m/^fcalias name (\S+) vsan (\S+)\s+pwwn (\S+)/)
{ my ($fcalias, $vsan, $pwwn) = ($1, $2, $3);
my $type = "pwwn";
print (OUTFILE "$fcalias;$vsan;$type;$pwwn;;;$switch_ip\n");
}
elsif ($_ =~ m/^fcalias name (\S+) vsan (\S+)\s+interface (\S+) swwn (\S+)/)
{ my ($fcalias, $vsan, $interface, $swwn) = ($1, $2, $3 ,$4);
my $type = "interface";
print (OUTFILE "$fcalias;$vsan;$type;;$interface;$swwn;$switch_ip\n");
}
else ($_ =~ m/^fcalias name (\S+) vsan (\S+)/)
{ my ($fcalias, $vsan) = ($1, $2);
my $type = "none";
print (OUTFILE "$fcalias;$vsan;$type;;;;$switch_ip\n");
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
要回答标题中的问题,您可以
向前看下一行,或者
在阅读下一行时修补阅读上一行的结果 当您读取下一行时
对于根本不起作用的
else
,您是否知道您已经注释掉了其中的一半?并且它不写入 OUTFILE ? 您提供的输入都不会到达它吗?您正在跳过空行并匹配所有其他行。当匹配到^fcalias(或者数据用完)时执行else的主体,发现它设置的变量还没有被重置;另外,在 pwwn|interface 情况下重置这些变量。要避免使用中间文件但仍使用旧代码,请使用带有管道的 open 。例如,
To answer the question in the title, you either
Look ahead to the next line, or
Patch the result of reading the previous line, when you read the next one.
Of the
else
not working at all, are you aware that you've commented half of it out? And that it doesn't write to OUTFILE ? And that none of your provided input will reach it? You're skipping empty lines and matching every other line. Perform the body of the else when you match ^fcalias (or run out of data) and find that the variables it sets have not been reset; also, reset those variables in the pwwn|interface cases.To avoid an intermediary file but still use your older code, use open with a pipe. E.g.,
如果逐行读取数据会让你的工作变得更加困难,你为什么要这么做呢? slurping 的问题在于所有内容都会同时进入内存。如果您的文件足够小,这应该不是问题。
对您的风格的附加评论。您不应使用全局文件句柄 (
OUTFILE
)。这些是全局变量,伴随着它们带来的所有问题。如果您在递归函数中打开了全局文件句柄,例如您将始终关闭并重新打开文件句柄。最好使用本地文件句柄,如
open my $outfile, '>', $outpath or die
。If reading the data line by line makes your work much harder, why do you it? The issue with slurping is that everything ends up in memory at once. If you file is small enough this should not be a problem.
An additional comment on your style. You should not use global file handles (
OUTFILE
). These are global variables with all the issues that come with them. If you have an open with global file handle in a recursive function e.g. you will always close and reopen the file handle.Better use local file handles as in
open my $outfile, '>', $outpath or die
.