2016-04-14 60 views
0

我有下面的代码,我试图在一个变量模式grep。该变量中有一个多行文本。Perl grep一个模式的多行输出

$output

多行文本看起来像这样

_skv_version=1 
COMPONENTSEQUENCE=C1- 

BEGIN_C1 
     COMPONENT=SecurityJNI 
TOOLSEQUENCE=T1- 
END_C1 
CMD_ID=null 
CMD_USES_ASSET_ENV=null_jdk1.7.0_80 
CMD_USES_ASSET_ENV=null_ivy,null_jdk1.7.3_80 
BEGIN_C1_T1 
CMD_ID=msdotnet_VS2013_x64 
CMD_ID=ant_1.7.1 
CMD_FILE=path/to/abcI.vc12.sln 
BEGIN_CMD_OPTIONS_RELEASE 
    -useideenv 

我使用到grep的模式

use strict; 
use warnings; 

my $cmd_pattern = "CMD_ID=|CMD_USES_ASSET_ENV="; 
my @matching_lines; 
my $output = `cmd to get output` ; 
print "output is : $output\n"; 

if ($output =~ /^$cmd_pattern(?:null_)?(\w+([\.]?\w+)*)/s) { 
     print "1 is : $1\n"; 
      push (@matching_lines, $1); 
    } 

我正在从$output预期多输出,但正则表达式模式匹配的代码我正在使用$output没有给我任何结果。

所需的输出

jdk1.7.0_80 
ivy 
jdk1.7.3_80 
msdotnet_VS2013_x64 
ant_1.7.1 

回答

1

关于你的正则表达式:

  • 你需要一个while,不是if(否则你将只匹配一次);当你做出这种改变,你还需要在/gc修饰符
  • 你并不真正需要的/s修改,作为一个让.比赛\n,这你没有利用的(见注末)
  • 您要使用的/m修改,使^每一个新行的开始相匹配,而不是字符串
  • 你想^之后添加\s*到你的正则表达式的仅仅是个开始,因为在至少一个你的线条你有领先的空间
  • 你需要pa在$cmd_pattern附近的租赁;否则,你得到两个选项,第一个是^CMD_ID=,第二个是CMD_USES_ASSET_ENV=其次是你的表达

的其余部分也可以简化(\w+([\.]?\w+)*)位下降到(.+)

其结果将是:

while ($output =~ /^\s*(?:$cmd_pattern)(?:null_)?(.+)/gcm) {    
    print "1 is : $1\n";    
    push (@matching_lines, $1); 
} 

话虽这么说,你的正则表达式仍然不会分裂ivyjdk1.7.3_80自身;我建议增加一个分裂和喜欢的东西去除_null

while ($output =~ /^\s*(?:$cmd_pattern)(?:null_)?(.+)/gcm) {   
    my $text = $1; 
    my @text; 
    if ($text =~ /,/) { 
    @text = split /,(?:null_)?/, $text; 
    } 
    else { 
    @text = $text; 
    } 

    for (@text) { 
    print "1 is : $_\n"; 
    push (@matching_lines, $_); 
    } 
} 

你留下了唯一的问题是孤行CMD_ID=null。我会把它留给你:-)

(我最近写了一篇关于正则表达式最佳实践的博客文章 - http://blog.codacy.com/2016/03/30/best-practices-for-regular-expressions/ - 你会发现在Perl中总是需要/s的提示;我提到的原因在这里,你不需要它是你没有使用你实际需要的那些,这可能意味着你不确定的含义/s