2017-01-31 2 views
0

Ich habe diesen Code geschrieben, der Dateien findet, die das Muster "Match" in der Zeichenfolge Str findet und druckt.Get Zeile von Regex-Match in C

#include <regex.h> 
#include <string.h> 
#include <stdio.h> 
int main(int argc, const char *argv[]) { 
    char *str = strdup("aaaaaaa match aaaaaaaaaaaaaaaaaaaa\n" 
         "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n" 
         "cc match ccccccccccccccccccccccccc"); 
    regex_t regex; 
    regmatch_t match; 
    regcomp(&regex, "match", REG_EXTENDED); 
    while(regexec(&regex, str, 1, &match, 0) != REG_NOMATCH) { 
     int beg = match.rm_so; 
     int end = match.rm_eo; 
     int len = end-beg; 
     char *match_string = str+beg; 
     match_string[len] = '\0'; 
     printf("%s\n", match_string); 
     str = str + end + 1; 
    } 
    return 0; 
} 

Mein Problem ist, dass ich herausfinden muss, auf welcher Zeile das Spiel beginnt. Vorzugsweise sollte dies mit mehrzeiligen Übereinstimmungen funktionieren, aber eine einzelne Zeile ist gerade in Ordnung. Hat Regex eine versteckte Funktion, mit der ich das Problem lösen kann?

+1

Normalerweise lesen Sie Zeile für Zeile und verarbeiten Zeile für Zeile, um zu verfolgen, welche Zeile außerhalb der Regex ausgeführt wird. –

+0

Warum verwenden Sie 'strtok()' nicht, um nach einer neuen Zeile oder einer anderen Methode zu teilen, um die Zeichenfolge zu teilen? – Stargateur

+0

Das ist eine mögliche Lösung, jetzt, wo ich darüber nachdenke, könnte ich eine Liste mit dem Beginn der einzelnen Übereinstimmungen führen und dann iterieren, um die Nummer von '\ n' vor dem Beginn jedes Spiels zu finden. –

Antwort

0

In diesem Code speichere ich alle Übereinstimmungen in einer verknüpften Liste und gehe dann durch die Zeichenfolge, um die Zeile der Übereinstimmung zu finden. Es scheint in den meisten Fällen gut zu funktionieren. Wenn jemand eine bessere Lösung kennt, lass es mich wissen.

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

typedef struct match_s match_t; 

struct match_s { 
    int beg; 
    match_t *next; 
}; 

int main(int argc, const char *argv[]) { 
    char *str = strdup("aaaaaaa match aaaaaaaaaaaaaaaaaaaa\n" 
         "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n" 
         "cc match ccccccccccccccccccccccccc"); 
    match_t *head = NULL;  
    match_t *tail = NULL;  
    char *c = str;    
    regex_t regex;    
    regmatch_t match;   
    regcomp(&regex, "match", REG_EXTENDED); 
    int prev = 0; 
    while(regexec(&regex, str, 1, &match, 0) != REG_NOMATCH) { 
     int beg = match.rm_so; 
     int end = match.rm_eo; 
     str = str + end + 1; 
     match_t *match = malloc(sizeof(match_t)); 
     match->beg = beg + prev; 
     match->next = NULL; 
     prev += end+1;  
     if(head == NULL) { 
      head = match; 
      tail = match; 
     } else { 
      tail->next = match; 
      tail = match; 
     } 
    } 
    int line = 0; 
    int i = 0; 
    for(i = 0; c[i] != '\0' && head != NULL; i++) { 
     if(c[i] == '\n') { 
      line++; 
     } else if(head->beg == i) { 
      printf("Match on line: %d\n", line); 
      match_t *tmp = head->next; 
      free(head); 
      head = tmp; 
     } 
    } 
    free(str); 
    return 0; 
} 
1

können Sie die Zeilen mit strtok() analysieren in jeder \n die Zeichenfolge zu teilen.

Zusätzlich eine struct mit jeder Zeile zu speichern, können verwendet werden:

typedef struct { 
    char *str; 
    size_t lineno; 
} line_t; 

Dann, wenn Sie wissen, wie viele \n in der Zeichenfolge vorhanden sind, können Sie eine Reihe von Strukturen schaffen:

line_t *lines = malloc((numlines+1) * sizeof(line_t)); 

Jede Zeile wird wie folgt gespeichert:

T Sie können einfach strtok() erneut verwenden, um Muster zwischen den Räumen zu überprüfen. Um Strings zu vergleichen, ist strcmp gut zu verwenden. Hier

ist einige Beispiel-Code:

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

typedef struct { 
    char *str; 
    size_t lineno; 
} line_t; 

int main(void) { 
    char str[] = "aaaaaaa match aaaaaaaaaaaaaaaaaaaa\n" 
       "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n" 
       "cc match ccccccccccccccccccccccccc"; 
    const char *key = "match"; 
    const char *delim1 = "\n"; 
    const char *delim2 = " "; 
    char *pattern; 
    size_t numlines = 0, count = 0; 

    for (size_t i = 0; str[i]; i++) { 
     if (str[i] == '\n') { 
      numlines++; 
     } 
    } 

    line_t *lines = malloc((numlines+1) * sizeof(line_t)); 
    if (!lines) { 
     printf("Cannot allocate %zu members\n", numlines+1); 
     exit(EXIT_FAILURE); 
    } 

    pattern = strtok(str, delim1); 
    while (pattern != NULL) { 
     lines[count].str = malloc(strlen(pattern)+1); 
     if (!lines[count].str) { 
      printf("Cannot allocate %zu bytes\n", strlen(pattern)+1); 
      exit(EXIT_FAILURE); 
     } 
     strcpy(lines[count].str, pattern); 
     lines[count].lineno = count+1; 
     count++; 

     pattern = strtok(NULL, delim1); 
    } 

    for (size_t i = 0; i < count; i++) { 
     pattern = strtok(lines[i].str, delim2); 
     while (pattern != NULL) { 
      if (strcmp(pattern, key) == 0) { 
       printf("pattern '%s' found on line %zu\n", key, lines[i].lineno); 
      } 
      pattern = strtok(NULL, delim2); 
     } 
     free(lines[i].str); 
     lines[i].str = NULL; 
    } 

    free(lines); 
    lines = NULL; 

    return 0; 
} 

Hinweis: Dieser Code verwendet dynamische Speicherzuweisung mit malloc() und free() ‚s die Zeiger am Ende. Wenn Sie möchten, dass ich diese mehr erkläre, lassen Sie es mich wissen.

+0

Danke für die Antwort, das funktioniert in den meisten Fällen gut. Ich plane, dass mein Programm die Muster "# include * <*>" anpasst. Ich kenne einige Fälle, in denen Programmierer diese in mehreren Zeilen ausführen. Daher muss ich mehrzeiliges Matching verwenden, es könnte schwierig werden, die Zeilen in einem Array zu speichern. Aber ich werde definitiv dafür Verwendung haben. –

+1

@ Robert.S Ja, ich denke, es gibt viele Möglichkeiten, dies zu tun. Ich denke, es ist einfacher zu benutzen als Regex obwohl. Regex ist manchmal schwierig zu benutzen. – RoadRunner