2010-11-08 80 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