ECMAScript Regex для многострочной строки

Я пишу процедуру загрузки для своего приложения, и она включает в себя чтение данных из файла и создание соответствующего объекта с соответствующими свойствами.

Файл состоит из последовательных записей (разделенных новой строкой) в следующем формате:

=== OBJECT TYPE ===
<Property 1>: Value1
<Property 2>: Value2
=== END OBJECT TYPE ===

Где значения часто представляют собой строки, которые могут состоять из произвольных символов, новых строк и т. д.

Я хочу создать std::regex, который может соответствовать этому формату и позволить мне использовать std::regex_iterator для чтения каждого из объектов в файл по очереди.

Однако у меня возникли проблемы с созданием регулярного выражения, соответствующего этому типу формата; Я просмотрел синтаксис ECMAScript и создал свое регулярное выражение следующим образом, но оно не соответствует строке в моем тестовом приложении:

const std::regex regexTest( "=== ([^=]+) ===\\n([.\\n]*)\\n=== END \\1 ===" );

И при использовании этого в следующем тестовом приложении не удается сопоставить регулярное выражение со строкой:

int main()
{
    std::string testString = "=== TEST ===\n<Random Example>:This is a =test=\n<Another Example>:Another Test||\n=== END TEST ===";

    std::cout << testString << std::endl;

    const std::regex regexTest( "=== ([^=]+) ===\\n([.\\n]*)\\n=== END \\1 ===" );
    std::smatch regexMatch;

    if( std::regex_match( testString, regexMatch, regexTest ) )
    {
        std::cout << "Prefix: \"" << regexMatch[1] << "\"" << std::endl;
        std::cout << "Main Body: \"" << regexMatch[2] << "\"" << std::endl;
    }

    return 0;
}

person Thomas Russell    schedule 16.06.2013    source источник
comment
Какой компилятор вы используете? Знаете ли вы, что str::regex не реализован (полностью/вообще) в некоторых компиляторах? g++ конкретно (последний раз проверял).   -  person Qtax    schedule 19.06.2013
comment
@Qtax Я использую Microsoft Visual Studio 2012 и реализацию стандартной библиотеки, которая поставляется с ней и, насколько мне известно, обеспечивает полную реализацию std::regex и связанных функций.   -  person Thomas Russell    schedule 19.06.2013
comment
@Shaktal, вы можете попробовать удалить части выражения (чтобы получить части совпадения), чтобы увидеть, какая часть нарушает шаблон?   -  person Martin Ender    schedule 19.06.2013


Ответы (2)


Ваша проблема намного проще, чем кажется. Этот:

const std::regex regexTest( "=== ([^=]+) ===\\n((?:.|\\n)*)\\n=== END \\1 ===" );

отлично работал на clang++/libc++. Кажется, что \n не помещается в скобки [] в регулярном выражении ECMAscript. Не забудьте использовать while regex_search вместо if regex_match, если вы хотите найти более одного экземпляра регулярного выражения внутри строки!

person Massa    schedule 18.06.2013
comment
Большое спасибо, это было именно то, что я искал! - person Thomas Russell; 19.06.2013

Попробуй использовать:

  1. ленивые квантификаторы:

    === (.+?) ===\\n([\\s\\S]*?)\\n=== END \\1 ===

  2. отрицательные классы и отрицательные прогнозы:

    === ((?:[^ ]+| (?!===))+) ===\\n((?:[^\\n]+|\\n(?!=== END \\1 ===))*)

  3. POSIX:

    === (.+?) ===\n((.|\n)*?)\n=== END [^=]+? ===

person Casimir et Hippolyte    schedule 16.06.2013
comment
Ни одно из этих регулярных выражений не соответствовало строке, хотя оба скомпилировались без исключения. Спасибо за помощь!! - person Thomas Russell; 16.06.2013
comment
Я попытался отредактировать, и первый не соответствует, а второй приводит к возникновению ошибки времени выполнения. - person Thomas Russell; 16.06.2013
comment
Я попробовал вашу реализацию POSIX, и ошибок времени выполнения не возникло, и регулярное выражение было успешно скомпилировано, но оно не соответствовало моей тестовой строке. Спасибо за вашу помощь! - person Thomas Russell; 17.06.2013
comment
@Shaktal: вы сделали тест с глупым примером, таким как a, чтобы он соответствовал a? - person Casimir et Hippolyte; 17.06.2013
comment
Да, если я скажу, что строка "abbc" и регулярное выражение "a([b]+)c" идеально совпадают. - person Thomas Russell; 17.06.2013