2010-11-08 79 views
1

我想要读取文件,例如test.test其中包含Perl readline问题

#test:testdescription\n 
#cmd:binary\n 
#return:0\n 
#stdin:|\n 
echo"toto"\n 
echo"tata"\n 
#stdout:|\n 
toto\n 
tata\n 
#stderr:\n 

我成功地了结这是#TEST后:; #cmd:等... 但是对于stdinstdout,我想将下一个#之前的所有行加到表@stdin@stdout之间。

我做一个循环while ($line = <TEST>)所以它会看每一行。如果我看到一个模式/^#stdin:|/,我想移动到下一行并将此值转换为 表,直到我看到下一个#

如何移动到while循环中的下一行?

回答

2

这种文件格式可以与一些创意好办选择合适的值$/

use strict; use warnings; 

my %parsed; 

{ 
    local $/ = '#'; 
    while (my $line = <DATA>) { 
     chomp $line; 
     my $content = (split /:/, $line, 2)[1]; 
     next unless defined $content; 
     $content =~ s/\n+\z//; 
     if (my ($chan) = $line =~ /^(std(?:err|in|out))/) { 
      $content =~ s/^\|\n//; 
      $parsed{$chan} = [ split /\n/, $content]; 
     } 
     elsif (my ($var) = $line =~ /^(cmd|return|test)/) { 
      $parsed{ $var } = $content; 
     } 
    } 
} 

use YAML; 
print Dump \%parsed; 

__DATA__ 
#test:testdescription 
#cmd:binary 
#return:0 
#stdin:| 
echo"toto" 
echo"tata" 
#stdout:| 
toto 
tata 
#stderr: 

输出:

--- 
cmd: binary 
return: 0 
stderr: [] 
stdin: 
    - echo"toto" 
    - echo"tata" 
stdout: 
    - toto 
    - tata 
test: testdescription
+1

Trixy Hobbitssssses !!! +1 :) – DVK 2010-11-09 12:18:57

1

更新每个用户的colmments

如果我理解正确的问题,你想在一个循环中读取下一行?

如果是这样,您可以:

  1. 只是做内循环读取另一条线。

    my $another_line = <TEST>; 
    
  2. 保留一些状态标志,并用它在循环的下一次迭代,并积累stdins之间的线路在缓冲区:

    my $last_line_was_stdin = 0; 
    my @line_buffer =(); 
    while ($line = <TEST>) { 
        if (/^#stdin:|/) { 
         # 
         # Some Code to process all lines acccumulated since last "stdin" 
         # 
         @line_buffer =(); 
         $last_line_was_stdin = 1; 
         next; 
        } 
        push @line_buffer, $line; 
    } 
    

    这种解决方案可能无法做你所需要的100%,但定义你需要在状态机实现中遵循的模式:读取一行。检查你的当前状态(如果它很重要)。根据当前状态和行中的模式,验证当前行做些什么(添加到缓冲区中?更改状态?如果更改状态,请根据最后状态处理缓冲区)

此外,根据您的评论,你的正则表达式中有一个错误 - 管道(|字符)在正则表达式中的意思是“或”,所以你说“如果行开头#stdin或匹配一个空的正则表达式” - 后一部分是总是如此,所以你的正则表达式会匹配100%的时间。你需要逃避“|”通过/^#stdin:\|//^#stdin:[|]/

+0

一两件事:当我把在 while($ line = ) { if($ line =〜/^stdin:| /) { print“l ine“; } } 它打印文件中的所有行。通常它应该只打印#stdin:|对? – Dung 2010-11-08 19:56:34

+0

第二个解决方案不能解决问题,因为我想在|之后的所有行直到我遇到# – Dung 2010-11-08 20:09:41

+0

@viet - 将其扩展为在一行中读取并追加到数组/累加标量,直到找到下一个stdin。另外,当stdin被找到时,而不是“next” - 到下一行,首先处理整个缓冲区/累加器并将其清空。我相应地编辑了答案 – DVK 2010-11-08 23:40:29