정규 표현 식 의 고급 특성
정규 표현 식 의 quantifier 는 모두 greedy 입 니 다.즉, 하나의 문자열 에 match 가 여러 개 있 으 면 정규 표현 식 은 가장 긴 것 과 일치 합 니 다."..........................................................................그래서 여 기 는 non - greedy [1] 를 사용 해 야 합 니 다.non - greedy 란 정규 표현 식 이 일치 할 때 가장 짧 은 match 를 선택 하 는 것 을 말한다.
>>> txt = "Hello World " >>> pat = r'<.>' >>> re.match(pat, txt).group() ''
다음은 예 를 하나 더 보 겠 습 니 다.
>>> txt = "abcdddd" >>> code = """ m = re.match(pat, txt) for s in m.groups() : print s """ >>> pat = "(a/w+)" >>> exec code abcdddd >>> pat = "(a/w+?)" >>> exec code ab >>> pat = "(a/w*?)" >>> exec code a
non - greedy 를 사용 한 후에 'a / w *?' 는 'a', 'a / w +?' 는 'a / w' 와 다 를 것 이 없 기 때문에 그 주요 용 도 는 쌍 을 이 루어 나타 난 문장 부호 와 일치 하 는 것 이다.따라서 이 정규 표현 식 은:
Single - line 과 Multi - line
싱글 라인 과 멀 티 라인 은 모두 '/ n' 을 겨냥 한 것 이다.그리고 '/ n' 의 처 리 는 '^' 와 '$' 의 일치 와 관련된다.쉽게 말 하면 Single - line 모드 에서 '/ n' 과 일치 할 수 있 습 니 다.
>>> match = lambda pat, str : re.match(pat, str).group() >>> match(".", "/n") Traceback (most recent call last): ... >>> match("(?s).", "/n") '/n' >>> match("(?m).", "/n") Traceback (most recent call last): ... >>> search = lambda pat, str: re.search(pat, str).group() >>> txt = """ 123abc def456 """ >>> search = lambda pat, str: re.search(pat, str).group() >>> search("(?s)/w$", txt) '6' >>> pat = "(?s)^.+$" >>> search(pat, txt) '/n123abc/ndef456/n' >>> search("(?m)/w$", txt) 'c' >>> search('(?m)^.+$', txt) '123abc'
multiline 의 주요 기능 은 '/ n' 을 한 줄 의 시작 과 끝 으로 하 는 것 이다.기본 적 인 상황 에서 '/ n' 은 '/ s' 와 일치 하 는 문자 로 여 겨 집 니 다.
>>> search("^[a-zA-z].*$", "Hello World!/n") 'Hello World!' >>> search("^[a-zA-z].*$", "/nHello World!/n") Traceback (most recent call last): ... >>> search("^/s*[a-zA-z].*$", "/nHello World!/n") '/nHello World!' >>> search("(?m)^[a-zA-z].*$", "/nHello World!/n") 'Hello World!'
한 마디 로 하면 멀 티 라인 과 single - line 은 모두 '/ n' 을 겨냥 한 것 으로 멀 티 라인 모드 에서 '/ n' 은 '^' 와 '$' 로 인 식 될 수 있다.single - line 모드 에서 "." 는 '/ n' 과 일치 할 수 있 습 니 다.이 로 인해 정규 표현 식 의 작업 방식 도 이에 따라 약간의 변화 가 생 길 것 이다.그러나 멀 티 라인 과 싱글 라인 은 이것 도 저것 도 아 닌 관계 가 아니다.
>>> match('.', '/n') Traceback (most recent call last): ... >>> match('(?s).', '/n') '/n' >>> search('(?m)^.+$', '/nhello/nworld/n') 'hello' >>> search('^.+$', '/nhello/nworld/n') Traceback (most recent call last): ...
전 자 는 기본 적 인 상황 에서 정규 표현 식 이 single - line 이 아니 라 는 것 을 증명 합 니 다.후 자 는 기본적으로 멀 티 라인 이 아니 라 는 것 을 증명 한다.
Backreference
앞 에는 괄호 로 regex 를 잡 았 고, 뒤 에는 / i (i 표시 숫자) 로 이 regex 를 인용 할 수 있 습 니 다.
>>> str = "Hello World " >>> pat = r"(.+)/1>" >>> re.match(pat, str) <_sre.sre_match object="" at=""> >>> m = re.match(pat, str) >>> code = """ for s in m.groups() : print s """ >>> exec code tag Hello World
다시 한 번 예 를 들 어 같은 알파벳 세 개 를 캡 처 하려 면 추가 합 니 다.
>>> pat = r'([a-zA-Z])/1/1'
backreferece 를 진행 할 때 는 반드시 raw 를 사용 해 야 합 니 다.string, 그렇지 않 으 면 역 슬 래 쉬 가 escape 에 의 해 떨 어 집 니 다.
한 표현 식 에 여러 group 이 있 으 면 backrefence 가 혼 란 스 러 워 집 니 다.이 때 그룹 을 backrefence 후보 에서 제외 할 수 있 습 니 다.
>>> txt = "Title" >>> pat = r'(?:.+?)/1>' >>> m = re.match(pat, txt) >>> m.groups() ('h1',)
표현 식 이 정말 복잡 하 다 면 그룹 이름 도 고려 할 수 있 습 니 다.그룹 이름 문법 이 복잡 합 니 다.우선 이름 을 지 을 때 는 '? P', 인용 할 때 는 'P = Name', 바 꿀 때 는 '/ g' 을 사용 해 야 한다.또한 매 칭 에 성공 하면 그룹 이름 으로 하위 문자열 을 검사 할 수 있 습 니 다.
>>> txt = "Title" >>> pat = r".+?)>(?P.+)(?P=tag)>" >>> m = re.match(pat, txt) >>> print m.group() Title >>> print m.group("tag") h1 >>> re.sub(pat, '/g ', txt) 'Title '
assertion
Python 의 re 는 두 가지 assertion 이 있 는데 그것 이 바로 lookhead assertion 과 lookbehind assertion 이다.lookahead 란 이 assertion 이 정규 표현 식 의 앞부분 에 서 비 스 를 제공 하 는 것 을 말 하기 때문에 assert 는 정규 표현 식 의 후반 부 일 것 입 니 다.lookbehind 도 마찬가지다.
>>> def re_show(pat, s): print re.compile(pat, re.M).sub("{/g<0>}", s.rstrip()),'/n' >>> txt = "Micheal Jordan and Micheal Jackson" >>> pat = "(Micheal)(?= Jordan)" >>> re_show(pat, txt) {Micheal} Jordan and Micheal Jackson >>> pat = "(Micheal)((?i)(?=/s+jordan))" >>> re_show(pat, txt) {Micheal} Jordan and Micheal Jackson
이 예 를 들 어 lookahead assertion 은 match 에 참여 하지 않 는 것 외 에 group 과 별 반 다 르 지 않다.사실 그것 은 주로 교체 하 는 데 쓰 인 다.
>>> txt = "Micheal Jordan and Micheal Jackson" >>> pat = "(Micheal)(?= Jackson)" >>> re.sub(pat, "Phil", txt) 'Micheal Jordan and Phil Jackson'
lookahead assertion 은 positive 와 negative 두 가지 로 나 뉘 는데 앞에서 들 은 것 은 모두 positive 의 예 입 니 다. negative 는 positive 와 비슷 합 니 다. 다만 기 호 를 '?!' 로 바 꾸 었 을 뿐 입 니 다.
>>> txt = "Bill Clinton, Bill Joy, Bill Gates" >>> pat = "(Bill)(?! Joy)" >>> re_show(pat, txt) {Bill} Clinton, Bill Joy, {Bill} Gates >>> re.sub(pat, "William", txt) 'William Clinton, Bill Joy, William Gates'
lookbehind assertion 은 lookhead assertion 과 유사 하지만 중대 한 제한 이 있 습 니 다. pattern 은 반드시 길 어야 합 니 다. 수량 식별 자 (quantifier) 가 있어 서 는 안 됩 니 다.그것 의 positive 기 호 는 "? < =" 이다.negative 의 부 호 는 '?
>>> txt = "CPython, JPython, and Python.NET" >>> pat_positive = "(?<=J)(Python)" >>> pat_negative = "(?>> re_show(pat_positive, txt) CPython, J{Python}, and Python.NET >>> re_show(pat_negative, txt) C{Python}, JPython, and {Python}.NET
Tips
다음은 몇 가지 작은 예 를 들 겠 습 니 다.
tag = lambda s: r"(?s)%s)/b(?P.+?)>(?P.+?)%s>" % (s,s)
tag 는 element 와 일치 하 는 정규 표현 식 을 만 드 는 데 사 용 됩 니 다. h1 요소 와 일치 하 는 regex 를 만 들 려 면 tag (h1) 를 호출 하면 됩 니 다. 다음 과 같이 보 여 드 리 겠 습 니 다.
>>> tg = tag('anytag') >>> txt = r"""Hello world """ >>> re.match(tg, txt) <_sre.sre_match object="" at=""> >>> m = re.match(tg, txt) >>> m.group('tag') 'anytag' >>> m.group('attribute') ' a="yes" b="no"' >>> m.group('content') 'Hello world'
tag2 = lambda s : r"(?s)(.+?)%s>" % (s, s) GrabEntries = lambda s, tg : re.findall(tag2(tg), s)
다음은 예 를 하나 더 들 어 보 겠 습 니 다. 예 를 들 어 table 에는 tr 가 많 을 것 입 니 다. tr 에는 td 가 많 습 니 다. 함수 가 하나 있 으 면 table 의 element 를 전달 할 수 있 습 니 다. tr 의 list 로 돌아 가면 됩 니 다. 다음은 이 함수 입 니 다. 그런데 이 blog 는 문제 가 있어 서 제대로 table 에 올 라 갈 수 없습니다. 그래서 고 쳤 습 니 다.
>>> txt = """
123 abc red white """ >>> GrabEntries(txt, 'tr') ['/n/t123/n/tabc/n', '/n/tred/n/twhite/n'] [1] 내 원래 이해 에 문제 가 있 었 나 봐.원래 저 는 lookahead assertion 의 뜻 은 이 정규 표현 식 이 앞부분 에 대해 단언 을 했다 고 생각 했 습 니 다. 한참 동안 사람들 이 말 한 것 은 이 정규 표현 식 은 assertion 이 고 lookahead 는 표현 식 의 앞부분 에 만 관심 이 있다 는 뜻 입 니 다.표현 식 의 뒷부분 을 assert 한 것 이다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.