2012-07-17 69 views
3

输入文件:如何在匹配perl文本后提取所需的行?

{test test 
{*********************************************************************** 
{Rtest 
{*********************************************************************** 
{test 
{*********************************************************************** 
{* date 
{* 
{* Initial revision 
{* 
{*********************************************************************** 

{output} 

{output1} 

{output 2} 

{Test TEst TEST} 
{Test test test} 

{*********************} 

{********************} 

所需的输出:

{Output} 
{output1} 
{output2} 

脚本

use strict; 
use warnings; 

while (<DATA>) { 
    $line = $_; 
    chomp $line; 

    push(@lines, $line); 

    $line =~ s/^\s+//; 
    $line =~ s/\s+$//; 

    for (my $i = 0 ; $i <= $#lines ; $i++) { 
    if ($lines[$i] =~ m/(^{\**$)/) { 

     push(@matched, $lines[ $i + 1 ]); 
     print "$lines[$i+1]"."\n"; 
    } 
    } 
} 

我的输出:

{test test 
    {*********************************************************************** 
    {Rtest 
    {*********************************************************************** 
    {test 
    {*********************************************************************** 
    {* date 
    {* 
    {* Initial revision 
    {* 
    {*********************************************************************** 

我能够顶块匹配,但无法获得所需的前3行作为输出。从上面的匹配条件我试图提取下一行,但我得到一个空白的输出。 我错过了什么,在此先感谢。

+2

你的代码不能和'use strict'一起使用。有很多'需要显式包名'错误。另外,你已经重新定义了'$ line'。 – simbabque 2012-07-17 07:25:45

+1

如果你写下你的'输出'行匹配的特定条件,这将非常有帮助。现在,正如我所看到的,它可以是'/^\ {[^ {] *} $ /'pattern'匹配的文件中的前三行,或者是与其他行由空字符串组成,不包含'*'符号。它不应该是这样的:我们不需要讨论你想要的东西。 – raina77ow 2012-07-17 09:03:59

+0

我同意@ raina77ow – quinekxi 2012-07-17 09:17:32

回答

3

更新:最后一次编辑后,由于OP已更改了所需输出,所以此答案无效。

这可以做得很简单。只需删除所有以曲线{开头的行和空行的行。

use strict; use warnings; 
use Data::Dumper; 
my @output; 
while (<DATA>) { 
    chomp;   # remove newline 
    next if /^\{\*/; # We don't want lines starting with an open curly and an asterisk 
    next if /^\s*$/; # We also do not want lines that are empty 
    push @output, $_; 
} 

print Dumper \@output; 

输出:

$VAR1 = [ 
      'output', 
      'output1', 
      'output 2' 
     ]; 
+0

sinbabque:感谢您的输出,但是我编辑了需要将大括号合并在一起的请求输出,因为我们无法跳过它们。 – Anil 2012-07-17 07:48:30

+2

或者只是'egrep -v'^($ | \ {\ *)'文件' – tripleee 2012-07-17 07:54:48

+0

@tripleee:我喜欢那个!但这里不需要'\ *'。有些行像输入中的'{test',OP不想输出。 – simbabque 2012-07-17 08:01:27

3

这个方案是我最好的猜测,你可能想要的东西。它期望在命令行上输入文件。

我已经写了它,以便在以{*开头的行后打印下三个非空行。但我不能参透规则将排除线

{Rtest 

{test 

而且还包括你说你要的人。请再询问一下您是否需要进一步了解。

更新

也许你只想打印那些线是年底}?我已经改变了我的代码要做到这一点,而不是

use strict; 
use warnings; 

my @lines; 
my @matched; 

my $n = 0; 

while (<>) { 
    if (/^\s*\{\*+/) { 
    $n = 3; 
    } 
    elsif ($n and /\}\s*$/) { 
    print; 
    $n-- ; 
    } 
} 

输出

{output} 
{output1} 
{output 2} 
+0

至少你的作品。 =) – simbabque 2012-07-17 13:57:49

0

我不知道为什么你通过线积压回去,反复推搡他们到@matched - 特别是当他们没有匹配你说你想要得到的输出。这样做会更好...

while (<DATA>) { 
    print if m/^[{]o/i; 
} 

,但它并不能达到您指定的输出,因为没有相应于'{Output}''{output2}''{output}''{output 2}'没有输入线,所以,以防万一它不只是草率的规范,我们可能需要修改它。

while (<DATA>) { 
    next unless my ($n) = m/^[{]output\s*(\d)?[}]/i; 
    my $output = length $n ? 'output' : 'Output'; 
    say "{$output$n}"; 
} 
相关问题