홈으로 | 무료회원가입 | 아이디/비번찾기
추천음악방송 메인홈 1대1상담
운.영.자.1대1.상담
온라이브음악방송
온라이브스토어(앱다운로드)
OKTROT(무료음악채널)
뽕짝아가씨(무료음악채널)
아리랑가요(무료음악채널)
전통가요(무료음악채널)

환상의뽕짝파티 무료음악
트로트메들리관광 무료음악
보안∵서버∵쿠키
윈도우∵프레임
이미지∵배경
시간∵달력∵계산
상태바∵타이틀바
음악∵영상
폼∵전송∵테이블
키보드∵마우스
효과∵링크∵메뉴
Script∵php
기타
PHP 강좌
윈도우관련팁
웹관련팁
홈페이지제작팁
기본강좌
레지스트리
윈도우서버
리눅스서버
Android
정규표현식 프로그래밍 강좌 (2 - 2)
9년 전
6.2.4 에러 메시지 출력하기
---------------------------

regcomp 나 regexec 가 실패하게 되면, 0이 아닌 에러코드를 반환합니다. 이러한
에러코드들은 위의 6.2.2 와 6.2.3 에서 설명한 것들입니다. 에러코드에 해당하는
에러 문자열을 얻으려면 'regerror'를 사용할 수 있습니다.

  size_t regerror (int errcode,
                    const regex_t *preg,
                    char *errbuf,
                    size_t errbuf_size)

'errcode' 는 에러코드이고, 'preg' 는 에러가 발생한 패턴버퍼이며, 'errbuf' 는
에러 버퍼이며, 'errbuf_size' 는 'errbuf' 의 크기입니다.

regerror 는 'errcode' 에 대응하는 에러 문자열의 바이트 크기(널문자까지 포함)
를 반환합니다. 'errbuf' 와 'errbuf_size' 가 0이 아니라면, 'errbuf' 에 처음
errbuf_size-1 문자의 에러 문자열을 널문자를 추가해서 돌려줍니다.
'errbuf_size' 는 'errbuf' 의 바이트 크기보다 작거나 같은 양수이어야 합니다.
여러분들은, 'regerror' 의 에러 문자열을 담아내는 데 얼마만큼 크기의'errbuf'
가 필요한지 알아보기 위해서 'errbuf' 를 NULL로, 'errbuf_size' 를 0으로 해서
호출할 수 있습니다.

6.2.5 바이트 옵셋 사용하기
---------------------------

POSIX 에서, regmatch_t 형 변수는 GNU 의 레지스터와 비슷하지만, 똑같지는 않
습니다. POSIX 에서 레지스터의 정보를 얻으려면 regexec 에, regmatch 형 변수인,
0이 아닌 'pmatch'를 넘겨줄 수 있습니다. regmatch_t 형 구조체는 다음과 같습
니다.

  typedef struct {
    regoff_t rm_so;
    regoff_t rm_eo;
  } regmatch_t;

매칭 함수가 정보를어떻게 레지스터에 저장하는 지는 뒷부분에서 설명하겠습니다.

GNU Regex 의 'regs' 와 POSIX 의 'regs' 는 유사하게 대응합니다.

'reg' 의 'pmatch', pmatch[i]->rm_so 는 regs->start[i] 와 대응하고
pmatch[i]->rm_eo 는 regs->end[i] 와 대응합니다.

6.2.6 POSIX 패턴 버퍼를 Free 하기
----------------------------------

패턴 버퍼에 할당된 것을 free 하는 함수는 'regfree' 입니다.

void regfree (regex_t *preg)

'preg' 는 free 할, 할당된 패턴버퍼입니다. regfree 는 또한 'preg'의 'allocated'
와 'used' 필드를 0으로 설정합니다. 패턴 버퍼를 free 한 이후에는, 매칭 작업을
수행하기 전에 정규표현식을 해당 패턴 버퍼에 다시 컴파일해야 합니다.

6.2.7 POSIX Regex 로 egrep 만들기
----------------------------------

grep 은 기본 정규표현식을 사용하고, egrep 은 확장 정규표현식을 사용하는데,
여기서는 egrep 의 기능을 간단하게 구현해 보도록 하겠습니다.

지금까지 설명한 기능만으로도 egrep 의 기본적인 기능은 쉽게 만들 수 있습니다.
grep 류의 기본적인 기능은 '매칭' 이 아니라 '검색'이기 때문입니다.

우리가 만들'egrep' 을 'my_egrep' 이라고 부른다면, 'my_egrep' 의 기본적인
작동은 다음과 같이 하도록 합시다.

1) 특별한 옵션은 지원하지 않고, 인자는 모두 패턴이나 파일명으로 처리한다.
2) 입력파일명이 명시되지 않았을 경우에는 표준입력에서 받는다.
3) 컴파일 플래그는 'REG_EXTENDED' 를 사용하여 확장정규표현식을 지원한다.

추가적인 옵션을 지원하는 것은 소스를 조금씩 고치면서 시도해 보시기 바랍니다.

----------------------------------------------------------------------------

/* POSIX Regex 테스트 프로그램 : egrep 의 기본 기능 구현
*
* Designed by Han-donghun, 1997.5.31
*
* name    : my_egrep.c
*
* compile : First, you must have "regex.c" and "regex.h",
*              in the current directory.
*
*           To get "regex.o " , type "gcc -c regex.c"
*           Finally, to compile my_egrep.c, type follow.
*
*           "gcc -o my_egrep my_egrep.c regex.o"
*
* usage   : my_egrep pattern [files...]
*
* This is simple "pattern search" program
*        using POSIX regex, like egrep.
*/

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <errno.h>
#include "regex.h"    /* regex main header file */

void main(int argc, char *argv[]) {
  int ret = 0, error, i;
  char *msg;
  char buf[2048];
  FILE *fp;
  regex_t preg;

  if (argc <= 1) {
    fprintf(stderr, "usage: %s pattern [files..]\n", argv[0]);
    exit(1);
  }

  /* regex compile */
  if ((error = regcomp(&preg, argv[1],
        REG_EXTENDED | REG_NOSUB)) != 0) {
    ret = regerror(error, &preg, NULL, 0);
    msg = (char *)malloc(sizeof(char)*ret);
    regerror(error, &preg, msg, ret);
    fprintf(stderr, "%s: %s\n", argv[0], msg);
    free(msg);
    exit (1);
  }

  if (argc == 2) {
    while (fgets(buf, 2048, stdin) != NULL) {
      /* regex matching */
      if ((regexec(&preg, buf, 0, NULL, 0)) == 0) {
        printf("%s", buf);
      }
    }
  } else if (argc > 2) {
    for (i = 2; i < argc ; i++) {
      if ((fp = fopen(argv[i], "r")) == NULL) {
        fprintf(stderr, "%s: %s: %s\n", argv[0], argv[i], strerror(errno));
        continue;
      }
      while (fgets(buf, 2048, fp) != NULL) {
        /* regex matching */
        if ((regexec(&preg, buf, 0, NULL, 0)) == 0) {
          printf("%s", buf);
        }
      }
    }
  }
  regfree(&preg);
}

---------------------------------------------------------------------------

대소문자를 무시하게 만들려면, 정규표현식의 컴파일시에, regcomp 의
REG_EXTENDED 에 REG_ICASE 를 추가하시면 됩니다 (grep 류의 '-i' 옵션).
grep 류의 '-v' 나 -n' 옵션을 지원하는 것은 이제 간단하게 해결될 것입니다.

다음은 테스트 한 결과입니다.

---------------------------------------------------------------------------

$ gcc -o my_egrep my_egrep.c regex.o
$ my_egrep regcomp 정규표현식강좌.네번째
패턴 버퍼를 컴파일하려면 'regcomp' 를 사용합니다.
  int regcomp (regex_t *preg, const char *regex, int cflags)
  ................
$ my_egrep "^[0-9]+\.[0-9]+\b" 정규표현식강좌.네번째
6.2 POSIX Regex 함수
6.2.1 POSIX 패턴 버퍼
6.2.2 POSIX 정규표현식 컴파일
6.2.3 POSIX 매칭
6.2.4 에러 메시지 출력하기
6.2.5 바이트 옵셋 사용하기
6.2.6 POSIX 패턴 버퍼를 Free 하기
6.2.7 POSIX Regex 로 egrep 만들기
$
----------------------------------------------------------------------------

(다음 시간에 이어집니다..)
                                                                              
『리눅스 학당-리눅스 강좌 / 연재 (go LINUX)』 467번
제  목:정규표현식 프로그래밍 강좌 [마지막]
올린이:엠브리오(유형목  )    97/06/15 13:46    읽음:1809 관련자료 없음
-----------------------------------------------------------------------------
한동훈님의 정규식 라이브러리 마지막 강좌입니다.


-----------------------------------------------------------------------


#622   한동훈   (ddoch   )
[강좌] Regex (정규표현식) 라이브러리 (끝     06/09 17:01   459 line

GNU REGEX (정규표현식) 프로그래밍 강좌 (5)
-------------------------------------------

6.3 GNU Regex 함수
------------------

특별히 POSIX 나 버클리 UNIX 에 호환성을 생각하지 않아도 된다면, GNU regex
함수를 사용하는 것이 여러모로 좋을 지 모르겠습니다.
GNU regex 함수도 이전에 설명드린 POSIX 나 BSD regex 함수의 기능을 포함하
고 나머지 여러개의 복잡한 기능을 추가한 것입니다.

그럼, 하나씩 알아보도록 하겠습니다.

6.3.1 GNU 패턴 버퍼
--------------------

GNU regex 는 GNU 패턴 버퍼를 이용하여 컴파일된 정규표현식을 활용합니다.
이 패턴 버퍼는 POSIX regex 에서 설명하였으므로 건너뛰겠습니다.

6.3.2 GNU 정규표현식 컴파일
----------------------------

GNU regex 에서는 정규표현식을 검색하고 매칭하는 것을 둘다 할 수 있습니다.
GNU regex 에서도 POSIX 나 BSD regex 처럼, 먼저 정규표현식을 컴파일하여, 패턴
버퍼에 마련해 두어야 합니다. 이전과 마찬가지로 패턴버퍼는 어떤 문법으로 컴파
일되느냐에 따라 매칭이나 검색의 결과가 달라지게 마련입니다. 이러한 문법을 지
정하는 변수는 re_syntax_options 입니다. 따라서 컴파일을 하기전에 정확한 문법
을 세팅해 두는 것이 중요합니다.

GNU regex 에서 패턴을 컴파일하는 것은, re_compile_pattern 입니다.
re_compile_pattern 은 패턴버퍼를 인자로 취하는 데, 패턴 버퍼의 다음의 필드
는 초기화를 시켜주어야 합니다.

translate initialization
translate
         매칭이나 검색이전에 적용되는 변환테이블을 사용한다면 그 변환테이블
         에 대한 포인터로 초기화 시키줍니다. 변환테이블이 없다면 NULL로 초
         기화 시켜주면 됩니다. translate 는 GNU 패턴버퍼에서 char * 형 필드
         임을 상기하세요.
         변환 테이블에 대한 이야기는 뒷쪽에서 설명하겠습니다.

fastmap
         fastmap (re_search 로 빠른 검색에 사용됨) 을 사용하려면 그 포인터를
         지정하면 되며, 필요없다면 NULL로 지정하면 됩니다. 이 또한 char * 필
         드 입니다.

buffer
allocated
         re_compile_pattern 으로 컴파일된 패턴에 필요한 메모리를 할당하고
         자 할 경우에는 둘다 0이나 NULL로 초기화 하면 됩니다. (buffer 는
         unsigned char *, allocated 는 unsignedlong 형입니다. 0이나 NULL이
         나 결국에는 0입니다.) 여러분들이 이미 할당한 메모리 블록을 Regex
         에 사용하려면, buffer 는 그것의 주소로, allocated 는 블록의 바이트
         크기로 설정하면 됩니다.

         re_compile_pattern 은 컴파일된 패턴에 필요하다면 메모리를 확장하기
         위해서 realloc 를 사용합니다.


패턴을 컴파일 하려면 다음과 같이 사용하면 됩니다.

char *re_compile_pattern (const char *regex, const int regex_size,
                          struct re_pattern_buffer *pattern_buffer)

'regex' 는 정규표현식 문자열의 주소이고, 'regex_size' 는 그것의 길이입니다.
pattern_buffer 는 패턴버퍼의 주소입니다.

re_compile_pattern 이 성공적으로 해당 정규표현식을 컴파일하였다면 0(NULL)을
리턴하고, *pattern_buffer 를 컴파일된 패턴으로 설정을 합니다. 아울러 아래의
패턴버퍼 내의 필드를 세팅합니다.

buffer          컴파일된 패턴
used            buffer가 가르키는 곳에서 사용중인 바이트
syntax          re_syntax_options 의 현재값
re_nsub         'regex' 에서 보조표현식의 갯수
fastmap_accurate

re_compile_pattern 이 'regex' 를 컴파일 할 수 없다면, '6.2.2 POSIX 정규표현식'
에서 설명한 에러 문자열을 돌려줍니다.

6.3.3 GNU 매칭
---------------

GNU 매칭은 문자열속에서 가능한한 시작위치에서 명시된데로 매칭을 시킵니다.
한번 패턴을 패턴버퍼로 컴파일을 했다면, 문자열에서 패턴을 매칭 시킬수 있습니
다.

int re_match (struct re_pattern_buffer *pattern_buffer,
              const char *string, const int size,
              const int start, struct re_registers *regs)

pattern_buffer 은 컴파일된 패턴버퍼의 주소이고, string 은 매칭을 하고자 하는
문자열입니다. 이 문자열에는 NULL 이나 newline 을 포함할 수 있습니다. size 는
그 문자열의 길이이며, start 는 매칭하기를 원하는 문자열속의 인덱스(문자열 첫
문자의 인덱스는 0)입니다.

re_match 는 pattern_buffer 의 syntax 필드의 문법에 따라, 문자열 string 을,
pattern_buffer의 정규 표현식과 매칭을 시키는 역할을 합니다. 문자열과 매칭할
수 없다면 -1을 리턴하고, 내부적인 에러일 경우에는 -2를, 성공적일 경우에는
문자열과 매칭된 횟수를 돌려줍니다.

예를 들면, pattern_buffer 이 'a*'를 컴파일한 패턴버퍼라고 하고, string 이
'aaaaab'이며, 따라서 size는 6이 되고, start 는 2라고 가정한다면, re_match
는 3을 리턴합니다. 'a*' 는 문자열에서 마지막 세개의 'a'를 매칭시킬 것입니다.
start 가 0이라고 한다면, re_match 는 5를 리턴합니다. start 가 5나 6일 경우
에는 0을 반환합니다.
start 가 0에서 size 사이가 아니라면, re_match 는 -1을 반환합니다.

6.3.4 GNU 검색
---------------

검색하는 데 사용되는 함수는 re_search 입니다.

re_search 를 사용하기 전에 정규표현식을 컴파일 하셔야 겠죠?
re_search 의 정의는 다음과 같습니다.

int re_search (struct re_pattern_buffer *pattern_buffer,
               const char *string, const int size,
               const int start, const int range,
               struct re_registers *regs)

이 인자들은 re_match 와 유사합니다. 여기서 start 와 range 는 re_match 의
start 를 대응합니다.

range 가 양수이면, re_search 는 인덱스 start 에서 최초의 매칭을 시작하며
실패할 경우 start+1 에서 검색을 하며 계속 하나씩 나아가서 start+range 까지
수행합니다. range 가 음수라면, 인덱스 start 에서 첫 매칭을 수행하며, 이후에
-1씩 위치를 반대로 옮겨서 수행합니다.

start 가 0에서 size 사이가 아니라면, re_search 는 -1을 돌려줍니다. range 가
양수일 경우에는 re_search 는, 필요하다면 range 를 조절해서 start+range-1 이
0에서 size 사이가 되도록 하여 검색이 문자열 바깥으로 나가지 못하도록 합니다.
유사하게, range 가 음수라면, re_search 는 범위를 start+range+1 이 0에서 size
사이가 되도록 필요할 경우 조절하게 됩니다.

패턴버퍼의 fastmap 필드가 NULL 이라면, re_search 는 연속적인 위치로 매칭을 시
작하며, NULL 이 아니라면, fastmap 을 사용하여 좀 더 효율적으로 검색을 수행합
니다.

매칭이 한번도 되지 않는다면, re_search 는 -1을 반환하고, 매칭이 된다면 매칭이
시작된 위치의 인덱스를 돌려주며, 내부에러일 경우에는 -2를 돌려줍니다.

6.3.5 분리된 데이터로 매칭과 검색하기
--------------------------------------

re_match_2 와 re_search_2 를 사용하면, 두개의 문자열로 나누어진 데이터를 매칭
하거나 검색할 수 있습니다.

int re_match_2 (struct re_pattern_buffer *buffer,
                const char *string1, const int size1,
                const char *string2, const int size2,
                const int start,
                struct re_registers *regs,
                const int stop)


이 함수는 re_match 와, 두개 데이터의 문자열과 크기를 넘겨주고, 이후의 매칭을
원하지 않을 경우의 인덱스 stop 을 제외하면 유사합니다.
re_match 처럼, re_match_2 가 성공적으로 수행되었다면, 문자열 string 에서 매
칭된 횟수를 돌려줍니다. re_match 는 string1 과 string2 를, start 와 stop 인
자를 설정하여 regs 를 사용할 때 에는 연속된 것으로 취급합니다.

int re_search_2 (struct re_pattern_buffer *buffer,
                 const char *string1, const int size1,
                 const char *string2, const int size2,
                 const int start,
                 struct re_registers *regs,
                 const int stop)

이것은 re_search 함수와 유사합니다.

6.3.6 fastmap 으로 검색하기
----------------------------

몇 십만바이트 이상 되는 문자열에서 검색을 하려면 fastmap 을 사용해야 합니다.
순차적으로 연속적인 위치에서 검색을 한다면 아마도 상당한 시간이 걸릴 것입니다
. fastmap 은 내부적인 알고리즘을 유지하면서 최적의 검색을 수행합니다.

문자열 검색 시 효율을 높이기 위한 알고리즘은 많이 우리들에게 알려져 있습니다.
그들의 많은 부분들은 strstr과 같이 순차적으로 검색하는 것이 아니라 검색의 효
율을 높이기 위해서 내부의 테이블을 갖추고 현재 위치의 문자가 검색의 시작점이
될 수 있는지를 검사하며 최대한의 포인터를 건너뛰도록 설계된 경우가 있습니다.

fastmap 을 이러한 역할을 하는 테이블에 대한 포인터입니다.
즉, 여러분들의 문자셋(아스키문자 등)으로 인덱스된 하나의 배열입니다. 아스키
encoding 하에서는, 따라서, fastmap 은 256 개의 원소를 가집니다. 주어진 패턴
버퍼에 있어서 검색시 fastmap 을 사용하려고 할 때에는, 먼저 배열을 할당하고
배열의 주소를 패턴버퍼의 fastmap 에 지정해야 합니다. fastmap 은 일반적으로 사
용자가 직접 컴파일하거나 또는 re_search가 대신 할 수도 있습니다.fastmap 이
어떤 테이블을 가르키고 있다면, re_search 는, 컴파일된 패턴버퍼를 사용한 검색을
하기 이전에, 먼저 fastmap 을 자동적으로 컴파일합니다.

직접 수동으로 하려면 다음과 같이 사용하면 됩니다.

int re_compile_fastmap (struct re_pattern_buffer *pattern_buffer)

pattern_buffer 은 패턴버퍼의 주소입니다. 어떠한 문자 c 가 매칭에 있어서 시작
점이 될 수 있다면, re_compile_fastmap 은 'pattern_buffer->fastmap[c]'를 0이 아
닌 수로 지정을 합니다.
이 함수가 fastmap 을 컴파일 할 수 있다면 0을 리턴하고,내부에러일 경우에는 -2
를 리턴합니다. 예를 든다면, 패턴버퍼 pattern_buffer 가 'a|b' 를 컴파일한 패턴
을 보유하고 있다면, re_compile_fastmap 은 fastmap['a'] 와 fastmap['b'] 를 세트
한다는 것입니다. 'a' 와 'b' 는 매칭의 시작점이 될 수 있으니까요..

re_search 는 문자열의 각 원소들 중에서 fastmap 에 있는 것 중의 하나가 나올때
까지 차례로 비교합니다. 그리고 나서 그 문자에서부터 매칭을 시도합니다. 매칭이
실패할 경우에는 이러한 처리를 반복합니다. 따라서 이렇게 fastmap 을 사용할 경
우, re_search 는 매칭의 시작점이 될 수 없는 문자열의 위치에서 쓸데 없이 매칭
하려고 하는 시도를 줄임으로써 시간을 절약할 수 있는 것입니다.

fastmap 을 re_search 에서 사용하기를 원치 않을 경우에는 fastmap 필드에 NULL
(0)을 저장하면 됩니다. 물론 re_search 사용이전에 말이죠...

패턴버퍼의 fastmap 필드를 한번 초기화 했다면 다시 fastmap 을 컴파일 할 필요는
없습니다. re_search 는 fastmap 이 NULL 이면 컴파일을 하지 않으며, NULL 이 아
니라면 새로운 패턴에 새로운 fastmap 을 컴파일합니다.

6.3.7 GNU 변환 테이블
----------------------

패턴버퍼의 translate 필드를 변환 테이블로 설정하였다면, Regex 는 찾는 모든
문자열과 정규표현식에서 간단한 변환을 하기 위해 translate 로 지정된 변환
테이블을 사용합니다.

"변환테이블" 은 아스키와 같은 문자세트의 원소들로 인덱스된 배열입니다.
따라서 아스키코드에서는 변환테이블은 256개의 원소를 가집니다. 이 배열의 원소
들도 마찬가지로 여러분의 문자세트에 포함이 됩니다. Regex 함수가 문자 c를 만
났다면, 문자 c 대신 translate[c] 를 사용합니다.

가령 대소문자를 무시한 Regex 일 경우,

translate['A'] = 'A';
translate['a'] = 'A';
translate['B'] = 'B';
translate['b'] = 'B';
............

이렇게 값이 초기화 되어 있다면, 이후의 Regex 의 검색시 'a' 문자를 만난다면,
'a' 를 변환테이블의 인덱스로 하여 해당값으로 대신한다는 이야기입니다.
( translate['a'] 의 값은 'A' 이므로 'a' 대신 'A' 의 값을 적용함. )

그러나, 단한가지의 예외가 있다면, '\' 문자 뒤에 따라오는 문자는 변환하지 않
는다는 것입니다. '\' 문자가 이스케이프의 역할을 한다면, '\B' 와 '\b' 는 항
상 구별되는 것입니다.

이제 위와 같이, 소문자를 대문자로 변환하는, 대소문자를 무시하는 변환테이블을
초기화 하는 예를 보이겠습니다. (메뉴얼에 나와 있는 내용입니다. ^^)

    struct re_pattern_buffer pb;  /* 패턴 버퍼 */
    char case_fold[256];          /* 변환 테이블 */

    for (i = 0; i < 256; i++)
      case_fold[i] = i;
    for (i = 'a'; i <= 'z'; i++)  /* 소문자를 대문자로 변환 */
      case_fold[i] = i - ('a' -'A');

    pb.translate = case_fold;

이렇게 translate 에 변환 테이블의 주소를 지정하면 이후에변환테이블을 사용합
니다. 변환테이블을 사용하고 싶지 않다면 translate 에 NULL 을 넣어주시면 됩
니다. 만일, 패턴버퍼를 컴파일할 때나, fastmap 을 컴파일할 때, 패턴버퍼로 매칭
이나 검색을 수행할 때 이러한 테이블의 내용을 바꾼다면 이상한 결과를 얻을 것
입니다.

6.3.8 레지스터 사용하기
------------------------

사실 이 부분이 regex 에서 중요한 부분입니다.

지금까지는 regex 를 사용하여 어떤 문자열내에 해당 패턴(정규표현식)이 있느냐
없느냐만 따졌으나 이 레지스터를 사용하면 세부 매칭의 결과를 저장하게 됩니다.
즉, 문자열 인덱스 어디에서 어디까지 패턴과 매칭이 되었는지에 대한 정보를 확
보함으로써 나아가서는 문자열 치환 작업까지도 생각할 수 있습니다.

정규표현식에서 하나의 그룹은 전체적으로 정규표현식과 매칭되는 문자열의 하나
의 부분문자열과 매칭할 수 있습니다. 매칭작업을 수행할 때 각각의 그룹과 매칭
된 보조문자열의 시작과 끝이 기억됩니다.

이러한 검색이나 매칭시에는 GNU 매칭 및 검색 함수에 0이 아닌 'regs' 인자를 넘
겨줘야 합니다.

struct re_registers {
  unsigned num_regs;
  regoff_t *start;
  regoff_t *end;
};

레지스터 옵셋 타입(regoff_t) 는 'int'를 형정의 한 것 입니다.

start 와 end 의 i번째 원소는 패턴에서의 i번째 그룹에 대한 정보를 기록합니다.
이 start 와 end 는 다양한 방법으로 할당되는 데, 이것은 패턴버퍼의
regs_allocated 필드에 의존합니다.

제일 간편하고 유용한 방법은 regex 의 매칭함수로 하여금 각각의 그룹에 대한 정
보를 기록할 공간을 충분히 할당하게 하는 것입니다. regs_allocated 가
REGS_UNALLOCATED 라면, 매칭함수는 1+re_nsub(패턴버퍼의 다른 멤버) 만큼을 할당
합니다. 여분의 원소는 -1 로 설정하고, regs_allocated 를 REGS_REALLOCATE 로
설정합니다. 이후에 다시 호출할 경우에, 필요하다면 매칭함수는 공간을 더 할당
할 수 있습니다.

re_compile_pattern 은 regs_allocated 를 REGS_UNALLOCATED 로 설정하기 때문에,
GNU 정규표현식 함수에서는 위와 같은 행동이 기본으로 되어 있습니다.

POSIX 에서는 조금 다릅니다. 호출자에 매칭함수가 채울, 고정길이의 배열을 넘겨
줘야 합니다. 따라서 regs_allocated 가 REGS_FIXED 라면, 매칭함수는 그 고정배
열을 간단하게 채웁니다.

아래의 예제는 re_registers 구조체에 기록되는 정보를 보여줍니다. ('(' 와 ')'
이 그룹오퍼레이터라고 하고, 문자열 string 에서 첫번째 문자의 인덱스를 0이라
하겠습니다.)


ㄱ. 정규표현식이 또다른 그룹을 포함하지 않는, i번째 그룹을 가지고 있다면, 함
    수는 'regs->start[i]' 에 그룹과 매칭하는 보조문자열의 시작 인덱스를 저장
    하고, 'regs->end[i]' 에는 보조문자열의 끝 인덱스를 저장합니다.
    'regs->start[0]'과 'regs->end[0]' 에는 전체 패턴에 대한 정보가 들어갑니다.

  예를 들면, 'ab' 에 대해 '((a)(b))' 를 매칭시킨다면, 다음의 결과를 얻을 것입
  니다.

   * 0 in `regs->start[0]' and 2 in `regs->end[0]'
   * 0 in `regs->start[1]' and 2 in `regs->end[1]'
   * 0 in `regs->start[2]' and 1 in `regs->end[2]'
   * 1 in `regs->start[3]' and 2 in `regs->end[3]'

ㄴ. 그룹이 반복오퍼레이터 등을 사용하여 한번보다 더 많이 매칭된다면, 함수는
    마지막으로 매칭된 그룹에 대한 정보를 저장합니다.

  예를 들면, 'aa' 에 대해 '(a)*' 를 매칭시킨다면, 다음의 결과를 얻을 것입니다.

   * 0 in `regs->start[0]' and 2 in `regs->end[0]'
   * 1 in `regs->start[1]' and 2 in `regs->end[1]'

  여기에서 그룹 1 은 '(a)' 이지만, 뒤의 '*' 오퍼레이터로 인해 'aa' 와는 1번
  초과 매칭되므로, 마지막에 매칭되는 'a'에 대한 인덱스를 기록합니다.

ㄷ. i번째 그룹이, 어떤 성공적인 매칭에 관여하지 않는다면, 반복오퍼레이터는 0번
  반복을 허용하고, 함수는 'regs->start[i]' 와 'regs->end[i]' 를 -1로 채웁니다.

  예를 든다면, 'b' 에 대해 '(a)*b' 를 매칭하는 경우는 다음의 결과를 얻을 것
  입니다.

   * 0 in `regs->start[0]' and 1 in `regs->end[0]'
   * -1 in `regs->start[1]' and -1 in `regs->end[1]'

   여기에서 1번째 그룹인 '(a)' 는 매칭에 관여하지 않기 때문에 'regs->start[1]'
   과 'regs->end[1]' 은 -1로 됩니다.

ㄹ. i번째 그룹이 길이가 0인 문자열을 매칭한다면, 함수는 regs->start[i] 와
  regs->end[i] 를 "길이가 0인 문자열"의 인덱스로 설정합니다.

  예를 든다면, 'b' 에 대해 '(a*)b' 를 매칭하는 경우는 다음의 결과를 얻을 것
  입니다.

  * 0 in `regs->start[0]' and 1 in `regs->end[0]'
  * 0 in `regs->start[1]' and 0in `regs->end[1]'

  여기에서 '(a*)b' 는 위의 '(a)*b' 와는 다릅니다. 1번째 그룹인 '(a*)' 는
  'b' 의 앞부분의 빈 문자열과 매칭이 되므로 regs->start[1]과 regs->end[1] 은
  둘다 '0' 이 됩니다.

ㅁ. i번째 그룹이 j번째 그룹을 포함하고, j번째 그룹은 i번째 그룹에만 포함되는
    경우, 함수는 i번째 그룹의 매칭을 기록하고, regs->start[j] 와 regs->end[j]
    에는 j번째 그룹과 마지막으로 매칭된 것에 대한 정보를 기록합니다.

    조금 햇갈리기 쉬운 경우인데, 예를 들어보지요..
    'abb' 에 대해 '((a*)b)*'를 매칭시키는 경우를 봅시다.

    regs->start[0] 과 regs->end[0] 은 당연히 전체 문자열의 정보를 가지므로
    0(첫번째 문자 인덱스), 3(시작인덱스 + 길이로 보는 것이 좋을 듯..) 이
    됩니다.

   1:     ((a*)b)*       abb       : 1번째 그룹 첫 매칭 (0, 2)
          ^^^^^^^        ^^
          ((a*)b)*       abb       : 2번째 그룹 첫 매칭 (0, 1)
           ^^^           ^

   처음의 매칭에서,  1번째 그룹은 'ab' 와 매칭되고, 2번째 그룹은 'a'와 매칭
   됩니다.

          ^^^^^^^
   2:     ((a*)b)*       abb       : 1번째 그룹 둘째 매칭 (2, 3)
                 ^         ^

           ^^^
          ((a*)b)*       a b b     : 2번째 그룹 둘째 매칭 (2, 2)
                 ^          ^ (빈문자열)

    반복 오퍼레이터의 영향으로, 두번째 매칭에서, 1번째 그룹은 'b'와 매칭되고,
    2번째 그룹은 마지막 'b' 의 바로 앞의 빈문자열과 매칭됩니다.

   따라서, 위의 'ㄴ' 규칙 (그룹이 반복오퍼레이터 등을 사용하여 한번보다 더 많
   이 매칭된다면, 함수는 마지막으로 매칭된 그룹에 대한 정보를 저장한다.) 에 따
   라, regs->start[1], regs->end[1] 에는 2, 3 이 각각 기록되며, 그룹1은 그룹
   2를 포함하고 그룹2는 그룹1에만 포함되기 때문에, 마지막으로 매칭된 2번째 그
   룹의 기록값인 2, 2가 각각 regs->start[2] 와 regs->end[2] 에 각각 기록됩니
   다.

   결과를 정리하면,

   * 0 in `regs->start[0]' and 3 in `regs->end[0]'
   * 2 in `regs->start[1]' and 3 in `regs->end[1]'
   * 2 in `regs->start[2]' and 2 in `regs->end[2]'

   'abb' 에 대해 '((a)*b)*' 를 매칭한다면, 그룹2(괄호안쪽의 '(a)') 는 마지막
   매칭에 관여하지 않으므로 다음과 같은 결과를 얻습니다.

   * 0 in `regs->start[0]' and 3 in `regs->end[0]'
   * 2 in `regs->start[1]' and 3 in `regs->end[1]'
   * 0 in `regs->start[2]' and 1 in `regs->end[2]'

   조금 햇갈리는 분도 계실 것이고, 재미를 느끼는 분도 계실 것입니다. :)

ㅂ. 위와 같을 경우에, 매칭이 되지 않을 경우, 함수는 regs->start[i],
    regs->end[i]와 regs->start[j], regs->end[j] 를 모두 -1 로 설정합니다.

    예를 들면, 'c' 에 대해 '((a)*b)*c' 를 매칭한다면, 다음의 결과를 얻을 것
    입니다.

    * 0 in `regs->start[0]' and 1 in `regs->end[0]'
    * -1 in `regs->start[1]' and -1 in `regs->end[1]'
    * -1 in `regs->start[2]' and -1 in `regs->end[2]'

레지스터에 대한 이야기는 이걸로 마치겠습니다.

6.3.9 GNU 패턴버퍼를 free 하기
-------------------------------

패턴버퍼에서 할당된 필드를 free 하기 위해서는 이전에 설명드린 POSIX 함수
(6.2.6 의 regfree) 를 사용할 수 있습니다. POSIX 에서 사용하는 regex_t 는
GNU 의 re_pattern_buffer 와 동일합니다. 패턴버퍼를 free 한 이후에는, 어떤
검색과 매칭작업을 다시 수행하려면, 정규표현식을 패턴버퍼로 다시 컴파일하여
야 합니다.
추천추천 : 178 추천 목록
번호 제목
3,026
 여러 도메인들 간 쿠키 공유하기
3,025
 태그 사이에 있는 텍스트를 추출
3,024
 [JQuery] textbox focus on off일때 숫자 콤마 보여주기
3,023
 쿠키 생성,가져오기,삭제
3,022
 사용자 함수 모음
3,021
 마우스,키보드 제한 ( 오른쪽클릭,드래그,영역선택등..)
3,020
 [HTML5] <video> - DOM으로 제어하기
3,019
 HTML5 video 태그에서 영상 좌우반전
3,018
 PHP - 특정 태그 및 문자열 추출, 제거
3,017
 [PHP] define과 defined의 차이
3,016
 우클릭 완벽차단 스크립트
3,015
 iframe 높이 100% 맞추기
3,014
 curl 함수를 이용한 HTTP REFERER 변경
3,013
 윈도우10 시스템 파일 및 Dism 검사
3,012
 텍스트 줄바꿈, 글자자르기 CSS
3,011
 jQuery Mobile에서 유용한 코드 10가지.
3,010
 [PHP] dirname()함수와 $_SERVER 관련 상수들
3,009
 [PHP] 파일 크기, 사이즈 불러오는 함수, filesize()
3,008
 [jQuery] jQuery Quick API
3,007
 [ transition ] 링크 hover 색상 변화 속도 조절
3,006
 PHP 5.3.0 에서 사라진 함수들 대체
3,005
 어떤 파일들이 include 나 require 되었는지 확인하는 함수(get_included_files)
3,004
 PHP 날짜 형식 및 계산하기(날짜 더하고 빼기)
3,003
 jQuery Mobile에서 유용한 코드 10가지.
3,002
 값이 배열 안에 존재하는지 확인하는 in_array함수
목록
인기절정뽕짝파티
인기트로트모음
지루박디스코메들리
밤무대애창곡
전자올겐경음악
세월따라노래따라
가슴시린트로트
7080추억속으로
추억의가요방(가사포함)
CDN 추천곡
종합성인가요방
못잊을옛날노래
카바레 음악
트롯디스코팡팡
관광 메들리
트롯카페
가요감상실
추억의옛노래
스페셜가요광장
BillBoard Free
추천가요모음
경음악.전자올겐
스페셜음악여행
WOLRD POPs
K-POP\BillBoard
POP TOP BEST

최신인기가요특집
추천가요\인기
F뮤직 인기\발라드
F뮤직 애창\트로트
트로트성인가요
인기가요
프리미엄 POP
경음악\기타
프리미엄 최신가요
프리미엄 성인가요
뮤직트로트 부산광역시부산진구 가야동 ㅣ 개인정보취급방침
Copyright (C) musictrot All rights reserved.