2016-09-05 3 views
1

Я пытаюсь использовать регулярное выражение для анализа исходных файлов и поиска функций в программах на языке С, которые начинаются со слова «LOG», и за ним может следовать или не следовать второй символ из класса [1248AFM], который затем следует открывающей скобкой. Это разрабатывается под Windows с использованием mingw, но в конечном итоге будет скомпилировано и запущено под Linux с использованием gcc. Я использую учебник по регулярному выражению Яна Гойеертса в качестве руководства, и похоже, что то, что мне нужно, - это либо нуль, либо одно совпадение выражения выражения скобки, показанного выше. Нуль или один звучит так же, как метасимвол вопросительного знака, но в моих экспериментах я еще не смог заставить это работать после выражения скобки. Чтобы проиллюстрировать, что я пытаюсь сделать, у меня есть короткая программа, показанная ниже. В идеале я хотел бы иметь совпадение только на str1 и str2. Если я компилирую и запускаю его, как показано, я не получаю ни одного совпадения. Если я оставлю знак вопроса, следуя выражению скобки, я получаю соответствие только на str2, чего я ожидаю. В дополнение к вопросительному знаку, я также пробовал квантификатор интервала формы {0,1}, но также не имел успеха. Есть ли что-то иное, чем выражение в скобках, которое я должен использовать?POSIX regex - ноль или одно совпадение выражения скобки?

Dave

#include <stdio.h> 
#include <regex.h> 

int main(int argc, char **argv) { 
    regex_t regex; 
    int rtn = regcomp(&regex, "LOG[1248AFM]?(", 0); 
    if (rtn) { 
    printf("compile failed\n"); 
    return(1); 
    } 
    char *str1 = " LOG("; 
    char *str2 = " LOGM("; 
    char *str3 = " LOG"; 
    char *str4 = " LOGJ("; 

    int rtn1 = regexec(&regex, str1, 0, NULL, 0); 
    int rtn2 = regexec(&regex, str2, 0, NULL, 0); 
    int rtn3 = regexec(&regex, str3, 0, NULL, 0); 
    int rtn4 = regexec(&regex, str4, 0, NULL, 0); 
    printf("str1: %d\nstr2: %d\nstr3: %d\nstr4: %d\n", 
    rtn1, rtn2, rtn3, rtn4); 

    return(0); 
} 
+0

Не работает в основном, попробуйте 'int rtn = regcomp (& regex," LOG [1248AFM]? [(] ", REG_EXTENDED); вместо этого (расширенный использует круглые скобки как разделители групп, следовательно, квадратные скобки вокруг) – deamentiaemundi

+0

В BRE '?' Должно быть экранировано '\?' * (При поддержке) * –

+0

Casimir - Я уже пробовал это, но когда я скомпилировал сбой, –

ответ

2

Как Казимир и Ипполит сказал: вам нужно бежать ?, которые избежали меня, когда я сделал свой комментарий. Проблема в том, что вы используете строковый литерал, а это значит, что вам нужно избежать побега.

EDIT как пользователь kdhp, по праву принятый: ? является расширением Gnu для основного регулярного выражения. Но проблема остается прежней: необходимость ускользания побегов в C-литерале.

#include <stdio.h> 
#include <regex.h> 

int main(int argc, char **argv) { 
    regex_t regex; 
    // Gnu extension 
    // int rtn = regcomp(&regex, "LOG[1248AFM]\\?(",0); 
    // Basic regular expression 
    int rtn = regcomp(&regex, "LOG[1248AFM]\\{0,1\\}(",0); 
    if (rtn) { 
    printf("compile failed\n"); 
    return(1); 
    } 
    char *str1 = " LOG("; 
    char *str2 = " LOGM("; 
    char *str3 = " LOG"; 
    char *str4 = " LOGJ("; 

    int rtn1 = regexec(&regex, str1, 0, NULL, 0); 
    int rtn2 = regexec(&regex, str2, 0, NULL, 0); 
    int rtn3 = regexec(&regex, str3, 0, NULL, 0); 
    int rtn4 = regexec(&regex, str4, 0, NULL, 0); 
    printf("str1: %d\nstr2: %d\nstr3: %d\nstr4: %d\n", 
    rtn1, rtn2, rtn3, rtn4); 

    return(0); 
} 

дает

str1: 0 
str2: 0 
str3: 1 
str4: 1 
+0

Может быть, ответ должен также объяснить фундаментальные различия между поддерживаемыми диалектами регулярных выражений, то есть BRE vES ERE? – tripleee

+0

@ tripleee Я не лингвист, и я не знаю навоза о диалектах. Я программист, и поэтому я * знаю, что в тот момент, когда я выбираю регулярное выражение для решения проблемы, у меня будут две проблемы вместо этого и в одно мгновение. Кроме того: максимальная длина сообщения составляет 30 тыс. IIRC – deamentiaemundi

+0

Использование '\?' Является расширением GNU для POSIX BRE. EREs ('REG_EXTENDED') или выражения скобок (' \ {0,1 \} ') могут использоваться для переносимости. – kdhp

2

Части проблемы здесь проистекает из досадной путаницы между наборами функций различных регулярных выражениями диалектов.

Короткий рассказ, с REG_EXTENDED, вы получите значение grep -E (aka egrep) значения некоторых конструкций регулярных выражений.

"e?(grep){3,7}" 

, где не требуется обратные косые - знак вопроса ? делает предыдущее выражение необязательным, скобки сделать группировку, и фигурные скобки выражают обобщенные повторение (в данном случае, от трех до семи повторений).

Без REG_EXTENDED вы получаете семантику BRE, для которой требуется обратная косая черта перед каждым из них. Конечно, в строке C, чтобы создать буквальную обратную косую черту, вам понадобятся две обратные косые черты, потому что обратная косая черта является общим символом escape строки.

"e\\?\\(grep\\)\\{3,7\\}" 

Ниже приводится краткое объяснение истории, но вы можете прекратить читать здесь и сделать это.

Основные регулярные выражения (BRE) основаны на наборе функций оригинального grep от Ken Thompson. В оригинале grep не было группировки круглых скобок, обобщенной количественной оценки с фигурными скобками или даже вопросительного знака для выражения опциональности. Однако стандарт POSIX кодирует способ выражения этих конструкций даже в BRE. Подожди.

Расширенные регулярные выражения (ERE) основаны на функциональном наборе egrep, который был расширением grep главным образом Al Aho. Он ввел ряд новых функций, а также другую внутреннюю архитектуру, основанную на последующем продолжении исследований приложений теории автоматов на соответствие строк (речь идет о начале и середине 1970-х годов здесь).

Когда они были стандартизованы POSIX, стандартная введенная четность функции, но отличается от другого синтаксиса поверхности для этих диалектов. Несколько причудливое расширение синтаксиса grep, в котором на диалекте BRE было введено специальное значение некоторых символов, в которых обратные косые включают, а не escape,. Это делает BRE обратно совместимым с оригиналом grep (до тех пор, пока вы не использовали ненужные обратные косые черты в своих регулярных выражениях, где раньше они не имели особого значения), что было важным соображением, но, по общему признанию, бородавком-дизайнером.

+0

не ожидал, что вы тоже зашли так глубоко в историю ;-) – deamentiaemundi

+0

Тангенциально также наткнулся на это: https://medium.com/@rualthanzauva/grep-was-a-private-command-of-mine- для-совсем-а-времени-до-я сделал-это общественно-кен-Томпсон-a40e24a5ef48 # .u10922d6i – tripleee

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