обработка многострочного шаблона в perl

#regex #perl

#регулярное выражение #perl

Вопрос:

я работаю над добавлением поддержки новых языков для моей мобильной платформы.Мне нужно добавить запись для каждого языка в несколько файлов, поэтому я подумал сделать это с помощью perl.Чтобы автоматизировать этот процесс, я испытываю проблему с тем, как сопоставлять многострочные шаблоны в perl. Вот мой сценарий :

 const mmi_imeres_mode_details_struct g_ime_mode_array_int[] =
{      
     {
     INPUT_MODE_NONE,
     0,
     0,
     0,
     0,
     0,
     0
     },
    {
     INPUT_MODE_MULTITAP_LOWERCASE_ABC,
     STR_INPUT_METHOD_MENU_MULTITAP_abc,
     WGUI_IME_MULTITAP_LOWERCASE_ABC_IMG,
     INPUT_MODE_DEFAULT_ALTERNATE_METHOD,
     MMI_IME_ALL_EDITORS | MMI_IME_ENGLISH_ONLY_MODE | MMI_IME_ALPHABETIC | MMI_IME_LOWERCASE,
     MMI_IMM_WRITING_LANGUAGE_ENGLISH,
     "en-US"
     },
  

}

Сначала у меня возникла проблема, потому что в perl файл считывается по одной строке за раз.итак, я сначала преобразовал свой файловый поток в единую переменную.

 my $newstr = '';
open (FH, "$filename") || die "Could not open file.n";
while(<FH>)
{
    $newstr = $newstr.$_;

}  
  

Нет, кто-нибудь может мне помочь, как искать текст в {} , если это многострочный шаблон. пожалуйста, ответьте в ближайшее время … 🙂

Ответ №1:

Во-первых, есть лучшая идиома для извлечения файла:

 my $newstr;
{
    open my $fh, '<', $filename or die "Could not open file $filename.n$!n";
    local $/ = undef;
    $newstr = <$fh>;
}
  

Далее, вы можете установить модификатор /s в вашем регулярном выражении, который обрабатывает строку как одну строку, позволяя ‘.’ (точка) соответствовать чему угодно, включая новые строки. Но даже в этом нет особой необходимости, поскольку вы все равно не будете использовать ‘dot’ в своем регулярном выражении…..

 while(  
    $newstr =~ m/
        {        # Match the opening bracket.
        ([^}]*)  # Capture any number of characters that exclude '}'
        }        # Match the closing bracket.
    /gx          # Use /g for multiple matches, and /x for readability.
) {
    print "$1n";
}
  

Другим решением было бы установить разделитель входных записей, $ /, в ‘}’. Таким образом, вы читаете файл в виде фрагментов, которые заканчиваются закрывающей скобкой. Отличный трюк.

Комментарии:

1. Вы знаете, я не очень доволен своим предыдущим ответом. Хотя он технически корректен, он не учитывает более масштабную задачу, стоящую перед ним. Вы анализируете вложенные теги. Для этого используйте модуль синтаксического анализа; не пытайтесь создавать собственное решение для регулярных выражений. Он действительно быстро усложняется. Вместо этого используйте Parse::RecDescent или Parse::RecDescent::Simple для повышения точности, уменьшения головной боли и улучшения сна по ночам.

2. да, вы правы, в долгосрочной перспективе это не выгодно, но cpan довольно обширен в использовании. Но я постараюсь .. спасибо за ваше предложение .. действительно полезно …:)

3. Также взгляните на Regexp::Grammars .