2016-08-09 21 views
6

Ich benutze Regex, wenn ich es auf Shell verwenden, funktioniert es aber nicht innerhalb des C-Programms.Regex funktioniert nicht in C

Irgendwelche Gedanken bitte?

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' verwendet ERE Syntax, die Syntax zu \< und \> anpassen (ich glaube, es ERE nahe ist, mit einigen Erweiterungen). Übergeben Sie das Flag "REG_EXTENDED" an das 'regcomp'. Trotzdem bin ich mir nicht sicher, ob "\ b" von "regex.h" unterstützt wird. –

+0

Ihre C-Version verwendet einzelne umgekehrte Schrägstriche innerhalb einer C-Zeichenfolge. Das wird nicht funktionieren, da diese Backslashes nicht in Ihre Regex-Bibliothek übertragen werden. (Was ist?) – usr2564301

Antwort

3

grep -E verwendet einige verbesserte ERE Syntax, dass die {n,m} Klammern quantifier Sinn (und auch ( und )) müssen nicht entwertet werden (regex nicht der Fall in BRE).

Sie benötigen REG_EXTENDED Flagge zum regcomp, und auch weitergeben, da Sie keine Wortgrenze verwenden können, ersetzen Sie die ersten \b mit (^|[^[:alnum:]_]) „gleichwertig“. Sie müssen keine \b Hinter da ein : in das Muster direkt nach:

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

Der (^|[^[:alnum:]_]) Teil entspricht entweder den Beginn der Zeichenfolge (^) oder (|) ein Zeichen andere als alphanumerische oder einem Unterstrich.

Voll 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. Vielen Dank Wiktor Stribiżew. Es hat mir sehr geholfen. Mit freundlichen Grüßen. – CppLearner

+0

Großartig.Beachten Sie, dass 'regmatch_t pmatch [4]' und 'size_t nmatch = 4' von der Anzahl der im Muster definierten Fanggruppen abhängen:' 4' = 1 + Menge von '(...)' * Fang * -Gruppen. –

1

Wortgrenze Referenz

General
POSIX

Aus den obigen Links erscheint es POSIX unterstützt es eigene Wortgrenze Konstrukt ist.
Beachten Sie, dass diese Konstrukte [[:<:]], [[:>:]]nicht Klassen sind.

Da und ERE Verwendung als BRE gebunden ist, sollten Sie in der Lage sein, dies zu tun -

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

oder, da zwischen [cf] und : eine natürliche Wortgrenze ist, kann es zu reduzieren

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

ich habe nicht getestet, aber es funktioniert wahrscheinlich.
Und gegeben ist es tatsächlich unklar was dies intern tut, könnte es besser sein,
bleiben mit dieser Syntax.

Einige Motoren, wie Boost- die die POSIX-Option haben,