2016-08-09 17 views
6

Używam regex, gdy używam go na powłoce działa, ale nie w programie C.Regex nie działa w C

Wszelkie myśli proszę?

echo "abc:[email protected]" | grep -E "(\babc\b|\bdef\b):[0-9]{10}@([A-Za-z0-9].*)" //shell 

reti = regcomp(&regex,"(\babc\b|\bdef\b):[0-9]{10}@([A-Za-z0-9].*)", 0); //c program 
+5

'grep -E' wykorzystuje ERE składni (myślę, że jest blisko do ERE, z pewnymi ulepszeniami). Przekaż flagę 'REG_EXTENDED' do' regcomp'. Mimo to nie jestem pewien, czy '' b 'jest obsługiwane przez 'regex.h'. –

+0

Twoja wersja C wykorzystuje pojedyncze odwrotne ukośniki wewnątrz łańcucha C. To nie zadziała, ponieważ te ukośniki odwrotne nie zostaną przekazane do twojej biblioteki regex. (Co to jest?) – usr2564301

Odpowiedz

3

grep -E wykorzystuje pewną zwiększoną ERE składni oznacza, że ​​{n,m} kwantyfikatorów szelki (a także ( i )) nie muszą być uciekł (nie w tym przypadku w BRE regex).

Trzeba zdać REG_EXTENDED flagę do regcomp, a także, ponieważ nie można użyć granicę słowa, wymienić pierwszą \b z (^|[^[:alnum:]_]) „równoważne”. Trzeba nie spływu \b ponieważ istnieje : w schemacie po prawej:

const char *str_regex = "(^|[^[:alnum:]_])(abc|def):[0-9]{10}@([A-Za-z0-9].*)"; 

(^|[^[:alnum:]_]) część pasuje albo początek napisu (^) lub (|) char inny niż alfanumeryczny lub podkreślenia.

Pełna C demo:

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

int main (void) 
{ 
    int match; 
    int err; 
    regex_t preg; 
    regmatch_t pmatch[4]; 
    size_t nmatch = 4; 
    const char *str_request = "abc:[email protected]"; 

    const char *str_regex = "(^|[^[:alnum:]_])(abc|def):[0-9]{10}@([A-Za-z0-9].*)"; 
    err = regcomp(&preg, str_regex, REG_EXTENDED); 
    if (err == 0) 
    { 
     match = regexec(&preg, str_request, nmatch, pmatch, 0); 
     nmatch = preg.re_nsub; 
     regfree(&preg); 
     if (match == 0) 
     { 
      printf("\"%.*s\"\n", pmatch[2].rm_eo - pmatch[2].rm_so, &str_request[pmatch[2].rm_so]); 
      printf("\"%.*s\"\n", pmatch[3].rm_eo - pmatch[3].rm_so, &str_request[pmatch[3].rm_so]); 
     } 
     else if (match == REG_NOMATCH) 
     { 
      printf("unmatch\n"); 
     } 
    } 
    return 0; 
} 
+0

Plus 1. Wielkie dzięki Wiktor Stribiżew. Bardzo mi to pomogło. Z poważaniem. – CppLearner

+0

Świetnie.Pamiętaj, że 'regmatch_t pmatch [4]' i 'size_t nmatch = 4' zależą od liczby przechwytywanych grup zdefiniowanych we wzorcu:' 4' = 1 + ilość '(...)' * przechwytywanie * grup. –

1

Słowo Boundary referencyjny

General
POSIX

Z powyższych linków wydaje POSIX obsługuje swój własny granica słowo konstrukt.
Należy zauważyć, że te konstrukty: [[:<:]], są klasami , a nie.

Biorąc pod uwagę, że i przy użyciu ERE w przeciwieństwie do BRE, powinieneś być w stanie to zrobić -

reti = regcomp(&regex,"[[:<:]](abc|def)[[:>:]]:[0-9]{10}@([A-Za-z0-9].*)", REG_EXTENDED);

lub, ponieważ między [cf] i : jest granica naturalny słowo, może być zmniejszona do

reti = regcomp(&regex,"[[:<:]](abc|def):[0-9]{10}@([A-Za-z0-9].*)", REG_EXTENDED);

nie testowałem tego, ale to chyba działa.
I w rzeczywistości jest to niejasne co do tego, co robi to wewnętrznie, może być lepiej
trzymać się tej składni.

Niektóre silniki, jak Boost, które mają możliwość POSIX, dostosować składni \< i \>