HOWTO · C

C의 정규 표현식

이 기사에서는 C의 정규식에 대해 이야기할 것입니다.

이 페이지의 내용

POSIX 정규식 함수는 C 프로그램에서 패턴을 컴파일하고 문자열이 패턴과 일치하는지 검사할 수 있게 해 줍니다. 정규식은 C 언어 자체에 포함된 기능이 아닙니다. 이 글에서는 POSIX <regex.h> 인터페이스를 사용합니다.

POSIX를 사용하는 C 정규식

정규식은 텍스트에서 찾을 패턴을 나타냅니다. POSIX는 기본 정규식과 확장 정규식이라는 두 가지 주요 패턴 문법을 제공합니다. 아래 예제에서는 REG_EXTENDED를 사용해 확장 문법을 선택합니다.

대괄호 표현식은 집합에 포함된 문자 하나와 일치합니다. 예를 들어 [abc]는 a, b, c 중 하나와 일치하고, [[:digit:]]는 숫자 하나와 일치합니다. [[:alnum:]_]는 영숫자 또는 밑줄과 일치하며, [[:lower:]]는 현재 로캘에서 소문자 하나와 일치합니다. POSIX 문자 클래스는 대괄호 표현식 안에 써야 하므로 [:number:]나 [:word:] 같은 형식은 표준 문자 클래스가 아닙니다. 숫자에는 [[:digit:]]를 사용하고, 문자와 숫자 및 밑줄을 모두 허용하려면 [[:alnum:]_]를 사용하세요.

문자 클래스와 대소문자 구분 없는 비교를 비롯한 매칭 동작은 현재 로캘에 따라 달라질 수 있습니다. 애플리케이션에서 로캘별 규칙이 필요하다면 로캘을 명시적으로 설정하세요. 이 API는 POSIX 구현에서 제공되지만 C 언어 자체가 이를 보장하지는 않습니다.

regcomp()로 POSIX 정규식 컴파일하기

컴파일된 정규식을 저장할 regex_t 객체를 선언한 다음, 그 주소와 NUL 종료 패턴, 컴파일 플래그를 regcomp()에 전달합니다. REG_EXTENDED를 지정하면 +와 같은 연산자가 확장 정규식 문법으로 해석됩니다. 대소문자를 구분하지 않으려면 REG_ICASE를 추가하고, 부분 일치 위치가 필요하지 않다면 REG_NOSUB를 추가하세요.

컴파일에 성공하면 regcomp()는 0을 반환합니다. 0이 아닌 값은 오류 코드이며 errno 값은 아닙니다. 같은 regex_t 객체를 regerror()에 전달하면 오류 메시지를 만들 수 있습니다. 컴파일에 성공한 경우에만 regfree()를 호출하세요.

regexec()로 문자열을 검사하고 컴파일된 정규식 해제하기

컴파일된 regex_t와 NUL 종료 문자열을 regexec()에 전달합니다. 반환값이 0이면 일치하고, REG_NOMATCH이면 패턴과 일치하지 않는다는 뜻입니다. 그 밖의 값은 실행 오류를 나타내며 regerror()로 오류 메시지를 만들 수 있습니다. 부분 일치 위치가 필요하면 regmatch_t 항목의 배열과 배열 크기를 전달하세요. 첫 번째 항목에는 전체 일치의 위치가 기록됩니다. REG_NOSUB를 지정했다면 부분 일치 위치를 요청하지 마세요.

이 완전한 예제는 패턴 하나를 컴파일하고 문자열 두 개를 검사한 뒤 컴파일된 객체를 해제합니다. 컴파일 및 실행 오류는 regerror()를 통해 보고합니다. 제공된 성공 실행에서는 match와 no match가 차례로 출력되고 종료 코드는 0이었습니다. 이 출력 레이블은 변경하지 않은 예제에 들어 있으므로 영어로 표시됩니다.

예제를 실행해 보세요.

이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.

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

int main(void) {
    regex_t re;
    const char *pattern = "[[:alpha:]]+";
    int status = regcomp(&re, pattern, REG_EXTENDED);

    if (status != 0) {
        char message[256];
        regerror(status, &re, message, sizeof message);
        printf("compile: %s\n", message);
        return 1;
    }

    const char *samples[] = {"C language", "123"};
    for (size_t i = 0; i < sizeof samples / sizeof samples[0]; ++i) {
        status = regexec(&re, samples[i], 0, NULL, 0);
        if (status == 0) {
            puts("match");
        } else if (status == REG_NOMATCH) {
            puts("no match");
        } else {
            char message[256];
            regerror(status, &re, message, sizeof message);
            printf("execution: %s\n", message);
        }
    }

    regfree(&re);
    return 0;
}
match
no match

샘플은 각 반환값을 확인한 다음 사용하며, 두 문자열을 모두 검사할 때까지 컴파일된 정규식을 유지합니다. 제공된 실행의 종료 코드는 0이었습니다. 예제를 사용하려면 POSIX <regex.h> 구현이 필요합니다.