복잡 한 정규 표현 식 을 어떻게 구성 해 야 합 니까?

문 제 는 원래《복잡 한 정규 표현 식 을 어떻게 구성 하 는 지》였 으 나,약간의 다른 의미 가 있다 고 생각 되면 정규 식 이 원래 매우 간단 하 다 고 느낀다.나 는 사람들 에 게 그것 을 어떻게 작은 일 로 크게 만 드 는 지 가 르 치고 있다.반대로 복잡 한 정규 식 도 두 렵 지 않 고 적절 한 방법 을 찾 아 구성 하 겠 다 는 것 이다.무 거 운 것 을 피하 고 가 벼 운 것 을 선택 하 십시오.Snopo 가 제시 한 텍스트 는 다음 과 같 습 니 다.or and name='zhangsan'and id=001 or age>20 or area='%renmin%'and like 입 니 다.그 중에서 정확 한 SQL 조회 문 구 를 어떻게 추출 하 는 지 물 어보 십시오.간략하게 분석 하면 알 수 있 듯 이 중간 부분 은 요구 에 부합 되 고 양 끝 에 like,or,and 가 몇 개 있 을 뿐이다.구조 가 SQL 문법 에 맞 는 조회 문 구 를 해석 할 수 있 는 정규 표현 식 은 비교적 복잡 할 것 이다.그러나 구체 적 인 문제 에 대해 서도 더 간단 할 수 있다.상기 불량 구조의 SQL 문 구 는 프로그램 을 사용 하여 자동 으로 생 성 되 어야 하 며,양쪽 끝 에 문제 의 뜻 에 부합 되 지 않 는 텍스트 가 있 을 수 있 습 니 다.이 텍스트 들 만 제거 하면 됩 니 다.그래서 나 는 정규 표현 식 을 썼 다.s/^(?:(?)or|and|like)\s*)+|\s*(?:(?:or|and|like)\s*)+$//mi;,이렇게 하면 여러 줄 의 문자열 의 맨 끝 에 있 는 like,or,and 와 가능 한 공백 문 자 를 모두 제거 하고 나머지 내용 은 바로 원 하 는 것 입 니 다.나 누 어 다스 리 는 답 을 보 낸 후에 스 노 포 는 이런 게 으 름 피 우 는 방법 에 만족 하지 않 았 다.그 는 SQL 문법 이 요구 하 는 조건 에 맞 는 검색 어 를 쓸 수 있 는 정규 식 을 쓸 수 있 느 냐 고 계속 물 었 다.where 부분 만 고려 하면 됩 니 다.완전한 select 를 쓸 필요 가 없습니다.)확실히 문 제 를 신속하게 해결 하 는 측면 에서 볼 때 효과 적 으로 해결 할 수 있다 면 어떤 방법 을 써 도 된다.그러나 지식 을 배 우 는 측면 에서 볼 때 무 거 운 것 을 피하 지 않 고 꼬치 꼬치 캐 묻 는 것 이 올 바른 길이 다.그렇다면 이 SQL 쿼 리 문 구 를 어떻게 사용 하 는 지 살 펴 보 자.가장 간단 한 조회 문 구 는 진위 판단,즉 where 1 이 어야 한다.where True; where false,잠깐 만.이러한 문 구 는 정규 식 을 사용 하여 직접/(?:-?\d+|True|False)/i。 조금 복잡 한 단일 문 구 는 좌우 비교,즉

name like 'zhang%', age>25 , work in ('it', 'hr', 'R&D')
일 수 있다.이 를 단순화 하면 구 조 는 A OP B 로 바뀐다.그 중에서 A 대표 변수,OP 대표 비교 연산 자,B 대표 값.A:가장 쉬 운 A 는\w+일 거 예요.실제 상황 을 고려 하여 변 수 는 점 이나 탈 문 자 를 포함 합 니 다.예 를 들 어'table.salary'는/[\w.]+/로 기록 할 수 있 습 니 다.이것 은 비교적 추상 적 인 세분 화 이다.요구 가 까다 로 우 면 탈 문 자 를 좌우 양쪽 에 동시에 나타 나 게 할 수도 있다(조건 판단).OP:Where 에서 자주 사용 하 는 몇 가지 관 계 는:=,<,>,<,>=,<=,Between,Like,in 입 니 다.간단 한 정규 설명 을 사용 하면:/(?:[<>=]{가 됩 니 다.1,2}|Between|Like|In)/i。 •B:B 의 경우 변수,숫자,문자열,목록 세 가지 로 나 눌 수 있 습 니 다.간단 한 견 해 를 위해 서 여 기 는 산술 표현 식 을 고려 하지 않 습 니 다.◦변 수 는 A 의 정 의 를 직접 연장 하면 됩 니 다.군말 하지 않다.◦숫자:/\d+/를 사용 하여 정의 합 니 다.소수 와 음 수 를 고려 하지 않 는 다.◦문자열:작은 따옴표 문자열 과 작은 따옴표 문자열 을 포함 합 니 다.중간 에는 전의 되 는 따옴표 가 포 함 될 수 있다.나 는 다음 과 같은 따옴표 문자열 정규 표현 식 을 썼 다.1])*?\1/。그러나 거대 한 기계 의 부품 이기 때문에 이렇게 쓰 는 위험 은 매우 크다.우선,역방향 인용 을 사 용 했 습 니 다.그 다음 에 이 역방향 인용 은 전역 의 역방향 인용 번 호 를 사용 했다.나 는 이 문 제 를 해결 하기 위해 전역 번 호 를 자동 으로 생 성 하 는 함 수 를 썼 다.하지만 여기 서 세부 사항 을 이야기 하 는 것 은 너무 깊 은 것 이 아 닙 니까?먼저 틀 을 이야기 하고 세부 사항 을 말 해 야 한다.손 만 대면 디 테 일 한 바다 에 빠 져 서 는 안 된다.◦목록:목록 은(1,3,4)또는("it","hr","r&d")와 같은 동쪽 입 니 다.간단 한 변 수 는 쉼표 로 연결 되 고 양쪽 에 괄호 로 구성 되 어 있 습 니 다.목록 의 단일 항목 은 I 로 표시 되 며,숫자|문자열 을 대표 합 니 다.이 때 목록 은:/\(I(?:,I)*?\)/。이것 은 왼쪽 괄호,하나의 I,일련의 쉼표,I 로 구 성 된 다른 목록 항목(0 개 이상),오른쪽 괄호 를 나타 낸다.간단하게 공백 문 자 를 고려 하지 않 았 습 니 다.이로써 단일 문장의 정규 구 조 를 정리 할 수 있다.S=~/A OP B/i.S 는 여기 서 단일 문 구 를 대표 합 니 다.더욱 복잡 한 것 은 여러 개의 문장 으로 하나의 문장 으로 구성 되 고 중간 에 and 또는 or 로 연결 할 수 있다.하나의 문 구 를 합 리 적 으로 구성 하여 여러 개의 문 구 를 안정 적 으로 작성 하면 임 무 를 완성 할 수 있다.위의 예 시 를 따라 S 로 단일 문장 을 대표 하면 복합 문장 C 는 C=~S(?:or|and) S)*?/。이로써 초기 규모 의 조건문 해석 기 가 탄생 했다.다음은 python 을 예 로 들 어 한 걸음 한 걸음 이 루어 집 니 다.Python 실현 은 실현 을 제 시 했 지만 생각 을 중시 하고 코드 를 무시 하 십시오.
 
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
#author: rex
#blog: http://iregex.org
#filename test.py
#created: 2010-08-06 17:12

#generage quoted string;
#including ' and " string
#allow \' and \" inside
index=0
def gen_quote_str():

global index
index+=1
char=chr(96+index)
return r"""(?P<quote_%s>['"])(?:\\['"]|[^'"])*?(?P=quote_%s)"""% (char, char)


#simple variable
def a():
return r'[\w.`]+'

#operators
def op():
return r'(?:[<>=]{1,2}|Between|Like|In)'


#list item within (,)
#eg: 'a', 23, a.b, "asdfasdf\"aasdf"
def item():
return r"(?:%s|%s)" % (a(), gen_quote_str())


#a complite list, like
#eg: (23, 24, 44), ("regex", "is", "good")
def items():
return r"""\( \s*
%s
(?:,\s* %s)* \s*
\)""" % (item(), item())

#simple comparison
#eg: a=15 , b>23
def s():
return r"""%s \s* %s \s* (?:\w+| %s | %s )""" % (a(), op(), gen_quote_str(), items())

#complex comparison
# name like 'zhang%' and age>23 and work in ("hr", "it", 'r&d')
def c():
return r"""
(?ix) %s
(?:\s*
(?:and|or)\s*
%s \s*
)*
""" % (s(), s())

print "A:\t", a()
print "OP:\t", op()
print "ITEM:\t", item()
print "ITEMS:\t", items()
print "S:\t", s()
print "C:\t", c()
이 코드 가 내 기계 에서(Ubuntu 10.04,Python 2.6.5)실 행 된 결 과 는
 
A: [\w.`]+
OP: (?:[<>=]{1,2}|Between|Like|In)
ITEM: (?:[\w.`]+|(?P<quote_a>['"])(?:\\['"]|[^'"])*?(?P=quote_a))
ITEMS: \( \s*
(?:[\w.`]+|(?P<quote_b>['"])(?:\\['"]|[^'"])*?(?P=quote_b))
(?:,\s* (?:[\w.`]+|(?P<quote_c>['"])(?:\\['"]|[^'"])*?(?P=quote_c)))* \s*
\)
S: [\w.`]+ \s* (?:[<>=]{1,2}|Between|Like|In) \s* (?:\w+| (?P<quote_d>['"])(?:\\['"]|[^'"])*?(?P=quote_d) | \( \s*
(?:[\w.`]+|(?P<quote_e>['"])(?:\\['"]|[^'"])*?(?P=quote_e))
(?:,\s* (?:[\w.`]+|(?P<quote_f>['"])(?:\\['"]|[^'"])*?(?P=quote_f)))* \s*
\) )
C:
(?ix) [\w.`]+ \s* (?:[<>=]{1,2}|Between|Like|In) \s* (?:\w+| (?P<quote_g>['"])(?:\\['"]|[^'"])*?(?P=quote_g) | \( \s*
(?:[\w.`]+|(?P<quote_h>['"])(?:\\['"]|[^'"])*?(?P=quote_h))
(?:,\s* (?:[\w.`]+|(?P<quote_i>['"])(?:\\['"]|[^'"])*?(?P=quote_i)))* \s*
\) )
(?:\s*
(?:and|or)\s*
[\w.`]+ \s* (?:[<>=]{1,2}|Between|Like|In) \s* (?:\w+| (?P<quote_j>['"])(?:\\['"]|[^'"])*?(?P=quote_j) | \( \s*
(?:[\w.`]+|(?P<quote_k>['"])(?:\\['"]|[^'"])*?(?P=quote_k))
(?:,\s* (?:[\w.`]+|(?P<quote_l>['"])(?:\\['"]|[^'"])*?(?P=quote_l)))* \s*
\) ) \s*
)*
일치 효과 도 를 보십시오. 산술 표현 식 은 방금"간단 한 견 해 를 위해 산술 표현 식 을 고려 하지 않 겠 습 니 다"라 고 언급 한 것 으로 기억 합 니 다.그러나 산술 표현 식 을 해석 하 는 것 은 매우 재 미 있 는 화제 입 니 다.알고리즘 책 이 라면 모두 언급 합 니 다.물론 정규 표현 식 으로 도 설명 할 수 있다.그 주요 사 고 는
 
expr -> expr + term | expr - term | term
term -> term * factor | term / factor | factor
factor -> digit | ( expr )
과 코드:
 
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
#author: rex
#blog: http://jb51.net
#filename math.py
#created: 2010-08-07 00:44

integer=r"\d+"

factor=r"%s (?:\. %s)?" % (integer, integer)

term= "%s(?: \s* [*/] \s* %s)* " % (factor, factor)

expr= "(?x) %s(?: \s* [+-] \s* %s)* " % (term, term)

print expr
입 니 다.출력 과 일치 하 는 효과 도 를 보 세 요. 팁•복잡 한 정규 식 없 이 문 제 를 해결 할 수 있다 면 반드시 사용 하지 마 세 요.복잡 한 정규 식 을 써 야 한다 면 다음 과 같은 원칙 을 참고 하 세 요.큰 부분 에서 분석 해 야 할 텍스트 의 전체적인 구조 가 어떤 모습 인지 이해 하고 작은 부품 으로 나 뉜 다.작은 부분 부터 시작 하여 모든 작은 부품 을 실현 하려 고 노력 하고 모든 부분 이 완전 하고 견고 하 며 전체 국면 에 놓 아 도 충돌 하지 않 습 니 다.이 부품 들 을 합 리 적 으로 조립 하 다.분 리 된 장점:한 모듈 만 오류 가 발생 하고 다른 부분 이 틀 렸 을 때 신속하게 오 류 를 찾 아 BUG 를 제거 할 수 있 습 니 다.포획 괄호 를 조심스럽게 사용 하 라.자신 이 무엇 을 하고 있 는 지,부작용 이 있 는 지,그리고 실행 가능 한 해결책 이 있 는 지 를 알 지 않 는 한.짧 은 정규 식 에 있어 서 한두 개의 여분의 괄호 는 우아 함 을 해치 지 않 는 다.그러나 복잡 한 정규 식 에 있어 서 한 쌍 의 괄호 는 치 명 적 인 잘못 일 수 있다.가능 한 한 free-space 모드 를 사용 하 세 요.정규 표현 식 의 가 독성 을 높이 기 위해 주석 과 공백 문 자 를 자 유 롭 게 추가 할 수 있 습 니 다.

좋은 웹페이지 즐겨찾기