grep(regcomp), utf-8

sesame·2021년 12월 31일
0

교육

목록 보기
11/46

regcomp

pattern으로 넘어온 정규 표현식 문자열을 전용 데이터 형식 regex_t로 변환하여 첫번째 인자인 reg에 저장

int regcomp(regex_t *reg, const char *pattern, int flags);

return 성공하면 0반환하고, 실패하면 에러코드를 반환

  • 첫번째 인자 reg의 메모리 영역은 호출하기 전에 할당하여 그 포인터를 전달해야하는데, 그 외에도 regcomp()가 독자적으로 메모리를 확보하게 된다.

관련 flag 값

  • REG_EXTENDED : 확장 정규식을 지원(이것을 적용하지 않을시 POSIX 기본 정규 표현식 문법이 적용)
  • REG_ICASE : 일치 항목에서 대소문자를 무시
  • REG_NOSUB : 스트링은 전체 패턴과 일치해야 함
  • REG_NEWLINE : 줄 바꾸기 문자를 특수 줄의 끝 문자로 처리
    그런 다음 ] 및 $ 패턴으로 일치되는 행 경계를 설정하며 \n을 사용하여 명백하게 스트링 내에서만 일치될 수 있음
    (이 플래그를 생략하면 줄 바꾸기 문자는 다른 문자처럼 처리됩니다.)

regfree

regcomp에 할당한 메모리를 해제하는 함수

void regfree(regex_t *reg);

regexec

변환된 regex_t를 사용하여 실제로 문자열과 패턴을 조합하는 함수

int regexec(const regex_t *reg, const char *string, size_t nmatch, regmatch_t pmatch[], int flags);

return 인자로 넘긴 문자열 string이 패턴 reg에 적합할 경우 0을 반환, 아닐경우 REG_NOMATCH 반환

  • reg: regcomp()에서 컴파일된 패턴의 버퍼
  • string: 검사할 문자열
  • nmatch: 기록할 최대 일치 항목수 지정(nmatch가 0이면 pmatch 무시)
  • pmatch: 일치를 기록하는 곳

    typedef struct {
    regoff_t rm_so; //문자열의 시작에서 시작까지의 바이트 오프셋 일치하는 부분 문자열
    regoff_t rm_eo; //문자열 시작부터 오프셋보다 큰 값 일치하는 부분 문자열의 끝
    } regmatch_t;


  • REG_NOTBOL: 라인의 시작 패턴인 ^를 사용하지 못함
  • REG_NOTEOL: 라인의 마지막 패턴인 $를 사용하지 못함

regerror

regcomp는 성공하면 0반환하고, 실패하면 에러코드를 반환하는데, 이 에러코드를 에러 메시지로 변환하는 함수

size_t regerror(int errcode, const regex_t *reg, char *msgbuf, size_t msgbuf_size);

grep.c

int main(int argc, char *argv[]){
    regex_t pat;
    int err;
    int i;
    
    if (argc < 2) {
        fputs("no pattern\n", stderr);
        exit(1);
    }
    
    err = regcomp(&pat, argv[1], REG_EXTENDED | REG_NUSUB | REG_NEWLINE);
    
    if (err != 0) {
        char buf[1024];
        
        //err로 err설정, pat설정, buf에 bufsize만큼 저장
        regerror(err, &pat, buf, sizeof buf);
        //puts는 표준출력으로 줄단위 처리를 의식한 api라서 \n붙여서 출력
        puts(buf);
        exit(1);
    }
    
    if (argc == 2) {
        do_grep(&pat, stdin);
    }
    else {
        for (i = 2; i < argc; i++) {
            FILE *f;

            f = fopen(argv[i], "r");
            if (!f) {
                perror(argv[i]);
                exit(1);
            }
            do_grep(&pat, f);
            fclose(f);
        }
    }
    regfree(&pat);
    exit(0);
}

static void do_grep(regex_t *pat, FILE *src) {
    char buf[4096];
    
    //스트림 src로부터 한 줄 씩 읽으면서 패턴에 적합한 경우에만 출력해주면 됨
    while (fgets(buf, sizeof buf, src)) {
        if (regexec(pat, buf, 0, NULL, 0) == 0) {
            fputs(buf, stdout);
        }
    }
}

문자열 처리

c언어 문자열

문자열(char*)은 숫자의 배열

문자코드

ASCII 코드는 char형을 기반으로 한 문자와 숫자의 대응표

  • char형은 1byte(=8bit)이기 떄문에 표현할 수 있는 문자의 개수는 2의 8승(256개)
  • 영어를 제외한 웬만한 언어의 문자를 표현하기에는 턱없이 부족한 숫자이기 때문에 2바이트 이상의 코드표가 필요
  • 그래서 ASCII이외에 다른 문자코드 발전: 한글을 취급할 수 있는 문자코드(EUC-KR, CP949, UTF-8, UTF-16)

유니코드

기존의 수많은 언어의 문자 코드를 대부분 포함해 문자코드가 난립하는 상황을 해결하기 위해 고안

문자 코드의 구체적인 의미

  1. 부호화 문자 집합
    문자 집합(문자셋): 글자들의 집합
    부호화된 문자 집합(coded character ser, CCS): 이 집합안의 문자들에 음수가 아닌 정수들을 배정한 것

    KS X 1001, 1002, 1003, UCS(ISO-10646)

인코딩

부호화 문자 집합에 속하는 각 문자는 하나의 숫자와 대응된다.
그 번호를 실제 바이트 열로 적용할 때의 계산식이 인코딩(Character Encoding Scheme, CES)

1. 와이드 문자

모든 문자에 대해서 같은 바이트 수를 사용하는 인코딩

  • 프로세스 내에서 데이터를 처리 할 때 사용

2. 멀티 바이트 문자

문자의 종류에 따라 사용하는 바이트 수를 바꾸는 인코딩

  • 일반적으로 문자열의 저장 및 전송할 때 사용

참고

0개의 댓글