LoginSignup
2
2

More than 3 years have passed since last update.

Cで正規表現を使う

Last updated at Posted at 2019-07-15

正規表現で使う関数は次のように定義されている。
これらを使って正規表現をつかった検索を行う。

#include<regex.h>
int regcomp(regex_t *preg, const char *regex, int cflags); 
int regexec(const regex_t *preg, const char *string, size_t nmatch,regmatch_t pmatch[], int eflags);
size_t regerror(int errcode, const regex_t *preg, char *errbuf,size_t errbuf_size);
void regfree(regex_t *preg);

step1

まず、regcompを使って正規表現文字列をregexecで使えるようにコンパイルを行う。
regexに正規表現文字列を指定し、コンパイルされたものはpregに格納される。
cflagはregexecに対して影響を与えるフラグである。意味は以下の表の通り。

cflag 意味
REG_EXTENDED 拡張正規表現で検索を行う。
REG_ICASE 大文字小文字を無視する。
REG_NOSUB マッチした位置を教えない。
REG_NEWLINE 全ての文字にマッチするオペレータに改行をマッチさせない。

step2

次に、regexecを使って検索を行う。

pregにはregcompでコンパイルしたものを検索範囲となる文字列を指定する。
nmatchとpmatch[]はマッチした位置を取得するために使用するもの。
eflagsはregexecに対して影響を与えるフラグである。意味は以下の表の通り。

eflag 意味
REG_NOTBOL 行頭にマッチするオペレータが失敗する。
REG_NOTEOL 行末にマッチするオペレータが失敗する。

regexecは失敗時にREG_NOMATCHを返す。
マッチする文字列が無い場合もREG_NOMATCHを返す。

step3

regcompはregex_t構造体の中にマロックした領域を保存するようになっているため、これを解放するためにregfreeで最後に解放する。

エラー処理

regcompは失敗時にはエラーコードを返すようになっている。
このエラーコードを文字列化するにはregerrorを使う。

grepコマンド的なものを作ってみる。

example.c

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

int main(int argc, char *argv[]) {
    if (argc != 3) {
        fprintf(stderr, "usage:\n%s PATTERN FILENAME\n", argv[0]);
        exit(1);
    }

    int err;
    char err_str_buf[4096] = {0};

    // STEP1
    regex_t patbuf;
    err = regcomp(&patbuf, argv[1], REG_EXTENDED | REG_NOSUB | REG_NEWLINE);
    if (err != 0) {
        regerror(err, &patbuf, err_str_buf, sizeof(err_str_buf));
        fprintf(stderr, "regcomp: %s\n", err_str_buf);
        exit(1);
    }

    FILE *fp;
    char buf[1024] = {0};
    fp = fopen(argv[2], "r");
    if (fp == NULL) {
        perror(argv[1]);
        exit(1);
    }
    //STEP2
    while(fgets(buf, sizeof(buf), fp)) {
        if (regexec(&patbuf, buf, 0, NULL, 0) == 0) {
            fputs(buf, stdout);
        }
    }
    //STEP3
    regfree(&patbuf);
    fclose(fp);
    return 0;
}

実行結果

$ gcc -o example_program example.c
$ ./example_program reg.* example.c
#include <regex.h>
    regex_t patbuf;
    err = regcomp(&patbuf, argv[1], REG_EXTENDED | REG_NOSUB | REG_NEWLINE);
        regerror(err, &patbuf, err_str_buf, sizeof(err_str_buf));
        fprintf(stderr, "regcomp: %s\n", err_str_buf);
        if (regexec(&patbuf, buf, 0, NULL, 0) == 0) {
    regfree(&patbuf);

参考

2
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2