如何在下一行解析包含相关数据的数组

发布于 2025-01-04 06:02:26 字数 2607 浏览 1 评论 0原文

打开我的 $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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

分分钟 2025-01-11 06:02:26

要回答标题中的问题,您可以

  1. 向前看下一行,或者

  2. 在阅读下一行时修补阅读上一行的结果 当您读取下一行时

对于根本不起作用的else,您是否知道您已经注释掉了其中的一半?并且它不写入 OUTFILE ? 您提供的输入都不会到达它吗?您正在跳过空行并匹配所有其他行。当匹配到^fcalias(或者数据用完)时执行else的主体,发现它设置的变量还没有被重置;另外,在 pwwn|interface 情况下重置这些变量。

要避免使用中间文件但仍使用旧代码,请使用带有管道的 open 。例如,

open DATA, "fcalias-stuff |" or die $!;

To answer the question in the title, you either

  1. Look ahead to the next line, or

  2. 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.,

open DATA, "fcalias-stuff |" or die $!;
ㄟ。诗瑗 2025-01-11 06:02:26

如果逐行读取数据会让你的工作变得更加困难,你为什么要这么做呢? 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文