Regular Expression - 윈디하나의 솔라나라

목차

개요

POSIX BRE

POSIX ERE

POSIX BRE에 비해 아래와 같이 추가되거나 삭제되어있다.

GNU BRE/ERE

PCRE

설치

펄 정규표현식

Perl regular expressions를 읽어보자. 또한 pcresyntax(3)을 읽어보자.

구현

regexp_pcre.c
(830 바이트)
/*
    PCRE Sample
    WindyHana's Solanara http://www.solanara.net/solanara/regexp
    cc -o regexp_pcre -lpcre -I/usr/local/include -L/usr/local/lib regexp_pcre.c
*/
#include <stdio.h>
#include <string.h>
#include <pcre.h>

/*
* Match string against the extended regular expression in
* pattern, treating errors as no match.
*
* return 1 for match, 0 for no match
*/
#define OVECCOUNT 30
int match(const char *string, char *pattern) {
	int status;
	pcre *re;
	const char *error;
	int erroffset;
	int ovector[OVECCOUNT];
	re = pcre_compile(pattern, 0, &error, &erroffset, NULL);
	status = pcre_exec(re, NULL, string, strlen(string), 0, 0, ovector, OVECCOUNT);
	pcre_free(re);
	return status >= 1;
}

int main(int argc, char *argv[]) {
    printf("%s\n", match("Hello World", ".*") == 1 ? "match" : "no match");
    return 0;
}


pcretest

pcretest(1)은 pcre를 테스트해볼 수 있는 툴이다.
root@ ~ # pcretest -d -t
PCRE version 8.34 2013-12-15

  re> /(a|bc)x+yz/
Compile time 0.0032 milliseconds
------------------------------------------------------------------
  0  26 Bra
  3   7 CBra 1
  8     a
 10   7 Alt
 13     bc
 17  14 Ket
 20     x++
 22     yz
 26  26 Ket
 29     End
------------------------------------------------------------------
Capturing subpattern count = 1
No options
No first char
Need char = 'z'
data> abyz
Execute time 0.0017 milliseconds
No match
data> axyz
Execute time 0.0007 milliseconds
 0: axyz
 1: a
data>

pcregrep

pcregrep(1)grep(1)과 유사하지만 pcre 를 사용할 수 있는 grep 이다. pcregrep man page를 참조하자.

PCRE2

설치

구현

regexp_pcre2.c
(1,713 바이트)
/*
    PCRE2 Sample
    WindyHana's Solanara http://www.solanara.net/solanara/regexp
    cc -o regexp_pcre2 -lpcre2-8 -I/usr/local/include -L/usr/local/lib regexp_pcre2.c
*/
#include <stdio.h>
#include <string.h>
#define PCRE2_CODE_UNIT_WIDTH 8
#include <pcre2.h>

/*
* Match string against the extended regular expression in
* pattern, treating errors as no match.
*
* return 1 for match, 0 for no match
*/
#define OVECCOUNT 30
int match(const char *string, char *pattern) {
	int status;
	int errornumber;
	pcre2_code *re;
	pcre2_match_data *match_data;
	PCRE2_SIZE erroroffset;
	PCRE2_SIZE *ovector;

	re = pcre2_compile((const unsigned char*) pattern, PCRE2_ZERO_TERMINATED, 0, &errornumber, &erroroffset, NULL);
	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 0;
	}
	match_data = pcre2_match_data_create_from_pattern(re, NULL);
	status = pcre2_match(re, (const unsigned char*) string, strlen(string), 0, 0, match_data, NULL);
	if (status < 0) {
		switch (status) {
			case PCRE2_ERROR_NOMATCH: printf("PCRE2 No match\n"); break;
			default: printf("PCRE2 Matching error %d\n", status); break;
		}
		pcre2_match_data_free(match_data);
		pcre2_code_free(re);
		return 0;
	}
	ovector = pcre2_get_ovector_pointer(match_data);
//	printf("Match succeeded at offset %d\n", (int)ovector[0]);
	
	pcre2_match_data_free(match_data);
	pcre2_code_free(re);
	return status >= 1;
}

int main(int argc, char *argv[]) {
    printf("%s\n", match("Hello World", ".*") == 1 ? "match" : "no match");
    return 0;
}


pcre2test

pcre2test(1)은 PCRE2를 테스트해볼 수 있는 툴이다. 자세한 설명은 MAN페이지를 참조하자.

pcre2grep

pcre2grep(1)는 PCRE2를 사용한 grep 이다. 자세한 설명은 MAN페이지를 참조하자.

샘플

몇가지 유용한 정규표현식 샘플을 담았다. 모든 샘플은 POSIX ERE를 따랐다.

구현

솔라리스도 정규 표현식 라이브러리를 제공하지만, 아마 많은 경우 사용하지 않을 것이다. 유닉스마다 또는 리눅스 배포판마다 사용방법이 미묘하게 다르기 때문에, 시스템에서 제공하는 라이브러리를 사용하느니 차라리 미리 구현되어있는 라이브러리를 배포판에 포함하는 것이 더 편리하기 때문이다. 주로 regex - Henry Spencer's regular expression librariesPCRE - Perl Compatible Regular Expressions를 번들에 포함시키는게 더 편리하다. 솔라나라에서는 솔라리스 번들된 정규표현식 라이브러리의 사용방법에 대해 간단히 설명하겠다.

POSIX

다양한 형태의 정규 표현식 함수를 지원해준다.

regcomp, regexec

regcomp(3c), regexec(3c), regerror(3c), regfree(3c) 을 사용한 예제다.

regexp_posix.c
(829 바이트)
/*
    Regular Expression Sample
    WindyHana's Solanara http://www.solanara.net/solanara/regexp
    cc -o regexp_posix regexp_posix.c
*/
#include <stdio.h>
#include <regex.h>

/*
* Match string against the extended regular expression in
* pattern, treating errors as no match.
*
* return 1 for match, 0 for no match
*/
int match(const char *string, char *pattern) {
      int status;
      regex_t re;
      if (regcomp(&re, pattern, REG_EXTENDED | REG_NOSUB) != 0) {
           return(0);      /* report error */
      }
      status = regexec(&re, string, (size_t) 0, NULL, 0);
      regfree(&re);
      if (status != 0) {
            return(0);      /* report error */
      }
      return(1);
}

int main(int argc, char *argv[]) {
    printf("%s\n", match("Hello World", ".*") == 1 ? "match" : "no match");
    return 0;
}

regcmp, regex

regcmp(1), regcmp(3c), regex(3c) 을 사용한 예제다.

regexp_regcmp.c
(770 바이트)
/*
    Regular Expression Sample
    WindyHana's Solanara http://www.solanara.net/solanara/regexp
    cc -o regexp_regcmp regexp_regcmp.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <libgen.h>

/*
* Match string against the extended regular expression in
* pattern, treating errors as no match.
*
* return 1 for match, 0 for no match
*/
int match(const char *string, char *pattern) {
      char *newcursor, *ptr;
      char ret[9];
      ptr = regcmp(pattern, (char *)0); // ptr equal result of regexp(1) "char ptr[] = {021, 064, 00, 0};"
      newcursor = regex(ptr, string, ret);
      free(ptr);
      return(newcursor != NULL);
}
 
int main(int argc, char *argv[]) {
    printf("%s\n", match("Hello World", ".*") == 1 ? "match" : "no match");
    return 0;
}

regexp

regexp(5) 을 사용한 예제다.

regexp_regexp.c
(881 바이트)
/*
    Regular Expression Sample
    WindyHana's Solanara http://www.solanara.net/solanara/regexp
    cc -o regexp_regexp regexp_regexp.c
*/
#include <stdio.h>
#include <stdlib.h>

#define INIT       register char *sp = instring;
#define GETC()     (*sp++)
#define PEEKC()    (*sp)
#define UNGETC(c)  (--sp)
#define RETURN(c)  return;
#define ERROR(c)   regerr()
#include <regexp.h>

#define ESIZE 100;
/*
* Match string against the extended regular expression in
* pattern, treating errors as no match.
*
* return 1 for match, 0 for no match
*/
int match(const char *string, char *pattern) {
	char expbuf[100];

	compile(pattern, expbuf, &expbuf[100],'\0');

	if (step(string, expbuf)) {
		return 1;
	}
	return 0;
}

int regerr() {
	printf("ERROR");
}

int main(int argc, char *argv[]) {
    printf("%s\n", match("Hello World", ".*") == 1 ? "match" : "no match");
    return 0;
}

GNU

아래 예제는 GNU의 regexp 를 사용하는 예제로, 솔라리스에서는 컴파일되지 않는다.

regexp_gnu.c
(893 바이트)
/*
    Regular Expression Sample
    WindyHana's Solanara http://www.solanara.net/solanara/regexp
    gcc -o regexp_gnu regexp_gnu.c
*/

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

/*
* Match string against the extended regular expression in
* pattern, treating errors as no match.
*
* return 1 for match, 0 for no match
*/
int match(const char *string, char *pattern) {
      int status;
      struct re_pattern_buffer re;

      re.translate = 0;
      re.fastmap = 0;
      re.buffer = 0;
      re.allocated = 0;
      
      if (re_compile_pattern(pattern, strlen(pattern), &re)) {
           return(0);      /* report error */
      }
      status = re_match(&re, string, strlen(string), 0, NULL);
      regfree(&re);
      return status > 0;
}

int main(int argc, char *argv[]) {
    printf("%s\n", match("Hello World", ".*") == 1 ? "match" : "no match");
    return 0;
}

BSD

regexp_bsd.c
(567 바이트)
/*
    Regular Expression Sample
    WindyHana's Solanara http://www.solanara.net/solanara/regexp
    cc -o regexp_bsd regexp_bsd.c
*/

#include <stdio.h>
#include <re_comp.h>

/*
* Match string against the extended regular expression in
* pattern, treating errors as no match.
*
* return 1 for match, 0 for no match
*/
int match(const char *string, char *pattern) {
	if (re_comp(pattern) == 0) {
		return re_exec(string);
	}
	return 0;
}

int main(int argc, char *argv[]) {
    printf("%s\n", match("Hello World", ".*") == 1 ? "match" : "no match");
    return 0;
}
RSS ATOM XHTML 5 CSS3