2016-04-14 2 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); 
} 

Это, как говорится, регулярное выражение до сих пор не разделится ivy и jdk1.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/ - вы найдете там примечание, которое всегда должно содержать /s в Perl; причина, по которой я упоминаю здесь вам не нужно, чтобы вы не использовали те, которые вам действительно нужны, и это может означать, что вы не были уверены в значении /s)

Смежные вопросы