web-dev-qa-db-ja.com

Cの正規表現:例?

ANSI Cで正規表現を使用する方法のいくつかの簡単な例とベストプラクティスを追っています。man regex.hはそれほど役立ちません。

150
Dervin Thunk

正規表現は実際にはANSI Cの一部ではありません。ほとんどの(すべて?)* nixに付属するPOSIX正規表現ライブラリについて話しているように思えます。 CでPOSIX正規表現を使用する例を次に示します( this に基づく)。

#include <regex.h>        
regex_t regex;
int reti;
char msgbuf[100];

/* Compile regular expression */
reti = regcomp(&regex, "^a[[:alnum:]]", 0);
if (reti) {
    fprintf(stderr, "Could not compile regex\n");
    exit(1);
}

/* Execute regular expression */
reti = regexec(&regex, "abc", 0, NULL, 0);
if (!reti) {
    puts("Match");
}
else if (reti == REG_NOMATCH) {
    puts("No match");
}
else {
    regerror(reti, &regex, msgbuf, sizeof(msgbuf));
    fprintf(stderr, "Regex match failed: %s\n", msgbuf);
    exit(1);
}

/* Free memory allocated to the pattern buffer by regcomp() */
regfree(&regex);

あるいは、CでPerl互換の正規表現のライブラリである PCRE をチェックアウトすることもできます。Perl構文は、Java、Python、および他の多くで使用されている構文とほぼ同じです。言語。 POSIX構文は、grepsedviなどで使用される構文です。

211

それはおそらくあなたが望むものではありませんが、 re2c のようなツールはPOSIX(-ish)正規表現をANSI Cにコンパイルできます。これはLexの代わりとして書かれていますが、本当に必要な場合は、最後の速度で柔軟性と読みやすさを犠牲にしてください。

12

上記の答えは良いですが、PCRE2を使用することをお勧めします。これは、文字通りすべての正規表現の例をすぐに使用でき、古代の正規表現から翻訳する必要がないことを意味します。

これについては既に回答しましたが、ここでも役立つと思います。

クレジットカード番号を検索するCの正規表現

// YOU MUST SPECIFY THE UNIT WIDTH BEFORE THE INCLUDE OF THE pcre.h

#define PCRE2_CODE_UNIT_WIDTH 8
#include <stdio.h>
#include <string.h>
#include <pcre2.h>
#include <stdbool.h>

int main(){

bool Debug = true;
bool Found = false;
pcre2_code *re;
PCRE2_SPTR pattern;
PCRE2_SPTR subject;
int errornumber;
int i;
int rc;
PCRE2_SIZE erroroffset;
PCRE2_SIZE *ovector;
size_t subject_length;
pcre2_match_data *match_data;


char * RegexStr = "(?:\\D|^)(5[1-5][0-9]{2}(?:\\ |\\-|)[0-9]{4}(?:\\ |\\-|)[0-9]{4}(?:\\ |\\-|)[0-9]{4})(?:\\D|$)";
char * source = "5111 2222 3333 4444";

pattern = (PCRE2_SPTR)RegexStr;// <<<<< This is where you pass your REGEX 
subject = (PCRE2_SPTR)source;// <<<<< This is where you pass your bufer that will be checked. 
subject_length = strlen((char *)subject);




  re = pcre2_compile(
  pattern,               /* the pattern */
  PCRE2_ZERO_TERMINATED, /* indicates pattern is zero-terminated */
  0,                     /* default options */
  &errornumber,          /* for error number */
  &erroroffset,          /* for error offset */
  NULL);                 /* use default compile context */

/* Compilation failed: print the error message and exit. */
if (re == NULL)
  {
  PCRE2_UCHAR buffer[256];
  pcre2_get_error_message(errornumber, buffer, sizeof(buffer));
  printf("PCRE2 compilation failed at offset %d: %s\n", (int)erroroffset,buffer);
  return 1;
  }


match_data = pcre2_match_data_create_from_pattern(re, NULL);

rc = pcre2_match(
  re,
  subject,              /* the subject string */
  subject_length,       /* the length of the subject */
  0,                    /* start at offset 0 in the subject */
  0,                    /* default options */
  match_data,           /* block for storing the result */
  NULL);

if (rc < 0)
  {
  switch(rc)
    {
    case PCRE2_ERROR_NOMATCH: //printf("No match\n"); //
    pcre2_match_data_free(match_data);
    pcre2_code_free(re);
    Found = 0;
    return Found;
    //  break;
    /*
    Handle other special cases if you like
    */
    default: printf("Matching error %d\n", rc); //break;
    }
  pcre2_match_data_free(match_data);   /* Release memory used for the match */
  pcre2_code_free(re);
  Found = 0;                /* data and the compiled pattern. */
  return Found;
  }


if (Debug){
ovector = pcre2_get_ovector_pointer(match_data);
printf("Match succeeded at offset %d\n", (int)ovector[0]);

if (rc == 0)
  printf("ovector was not big enough for all the captured substrings\n");


if (ovector[0] > ovector[1])
  {
  printf("\\K was used in an assertion to set the match start after its end.\n"
    "From end to start the match was: %.*s\n", (int)(ovector[0] - ovector[1]),
      (char *)(subject + ovector[1]));
  printf("Run abandoned\n");
  pcre2_match_data_free(match_data);
  pcre2_code_free(re);
  return 0;
}

for (i = 0; i < rc; i++)
  {
  PCRE2_SPTR substring_start = subject + ovector[2*i];
  size_t substring_length = ovector[2*i+1] - ovector[2*i];
  printf("%2d: %.*s\n", i, (int)substring_length, (char *)substring_start);
  }
}

else{
  if(rc > 0){
    Found = true;

    } 
} 
pcre2_match_data_free(match_data);
pcre2_code_free(re);
return Found;

}

を使用してPCREをインストール:

wget https://ftp.pcre.org/pub/pcre/pcre2-10.31.Zip
make 
Sudo make install 
Sudo ldconfig

を使用してコンパイル

gcc foo.c -lpcre2-8 -o foo

詳細については私の答えを確認してください。

4
Qndel

これは、REG_EXTENDEDの使用例です。この正規表現

"^(-)?([0-9]+)((,|.)([0-9]+))?\n$"

スペイン語のシステムおよび国際的な10進数をキャッチできます。 :)

#include <regex.h>
#include <stdlib.h>
#include <stdio.h>
regex_t regex;
int reti;
char msgbuf[100];

int main(int argc, char const *argv[])
{
    while(1){
        fgets( msgbuf, 100, stdin );
        reti = regcomp(&regex, "^(-)?([0-9]+)((,|.)([0-9]+))?\n$", REG_EXTENDED);
        if (reti) {
            fprintf(stderr, "Could not compile regex\n");
            exit(1);
        }

        /* Execute regular expression */
        printf("%s\n", msgbuf);
        reti = regexec(&regex, msgbuf, 0, NULL, 0);
        if (!reti) {
            puts("Match");
        }
        else if (reti == REG_NOMATCH) {
            puts("No match");
        }
        else {
            regerror(reti, &regex, msgbuf, sizeof(msgbuf));
            fprintf(stderr, "Regex match failed: %s\n", msgbuf);
            exit(1);
        }

        /* Free memory allocated to the pattern buffer by regcomp() */
        regfree(&regex);
    }

}
2
diego campos