pyparsing에서 이것에 대한 문법을 작성하는 방법 : 단어 세트와 일치하지만 주어진 패턴을 포함하지 않습니다.
문제
나는 Python과 Pyparsing을 처음 사용합니다. 다음을 달성해야합니다.
내 샘플 텍스트 라인은 다음과 같습니다.
12 items - Ironing Service 11 Mar 2009 to 10 Apr 2009
Washing service (3 Shirt) 23 Mar 2009
항목 설명, 기간을 추출해야합니다
tok_date_in_ddmmmyyyy = Combine(Word(nums,min=1,max=2)+ " " + Word(alphas, exact=3) + " " + Word(nums,exact=4))
tok_period = Combine((tok_date_in_ddmmmyyyy + " to " + tok_date_in_ddmmmyyyy)|tok_date_in_ddmmmyyyy)
tok_desc = Word(alphanums+"-()") but stop before tok_period
이 작업을 수행하는 방법?
해결책
Skipto를 가장 적합한 pyparsing 클래스로 보는 것이 좋습니다. 불필요한 텍스트이지만 그 전에 거의 모든 것을 받아 들일 것입니다. Skipto를 사용하는 몇 가지 방법은 다음과 같습니다.
text = """\
12 items - Ironing Service 11 Mar 2009 to 10 Apr 2009
Washing service (3 Shirt) 23 Mar 2009"""
# using tok_period as defined in the OP
# parse each line separately
for tx in text.splitlines():
print SkipTo(tok_period).parseString(tx)[0]
# or have pyparsing search through the whole input string using searchString
for [[td,_]] in SkipTo(tok_period,include=True).searchString(text):
print td
둘 다 for
루프는 다음을 인쇄합니다.
12 items - Ironing Service
Washing service (3 Shirt)
다른 팁
MK Saravanan,이 특정 구문 분석 문제는 좋은 '올레 re :
import re
import string
text='''
12 items - Ironing Service 11 Mar 2009 to 10 Apr 2009
Washing service (3 Shirt) 23 Mar 2009
This line does not match
'''
date_pat=re.compile(
r'(\d{1,2}\s+[a-zA-Z]{3}\s+\d{4}(?:\s+to\s+\d{1,2}\s+[a-zA-Z]{3}\s+\d{4})?)')
for line in text.splitlines():
if line:
try:
description,period=map(string.strip,date_pat.split(line)[:2])
print((description,period))
except ValueError:
# The line does not match
pass
수율
# ('12 items - Ironing Service', '11 Mar 2009 to 10 Apr 2009')
# ('Washing service (3 Shirt)', '23 Mar 2009')
여기의 주요 작업자는 물론 다시 패턴입니다. 분리하자 :
\d{1,2}\s+[a-zA-Z]{3}\s+\d{4}
날짜에 대한 regexp입니다. tok_date_in_ddmmmyyyy
. \d{1,2}
한 숫자와 일치하고 \s+
하나 이상의 공백과 일치하고 [a-zA-Z]{3}
3 글자 등과 일치합니다.
(?:\s+to\s+\d{1,2}\s+[a-zA-Z]{3}\s+\d{4})?
주변 환경입니다 (?:...)
. 이것은 그룹화되지 않은 Regexp를 나타냅니다. 이것을 사용 하여이 regexp에 그룹 (예 : match.group (2))이 할당되지 않습니다. date_pat.split ()가 각 그룹이 목록의 구성원이되는 목록을 반환하기 때문에 중요합니다. 그룹화를 억제함으로써 우리는 전체 기간을 유지합니다. 11 Mar 2009 to 10 Apr 2009
함께. 끝의 물음표는이 패턴이 0 또는 한 번에 발생할 수 있음을 나타냅니다. 이를 통해 Regexp가 두 가지 모두 일치 할 수 있습니다23 Mar 2009
그리고 11 Mar 2009 to 10 Apr 2009
.
text.splitlines()
텍스트를 나눕니다 \n
.
date_pat.split('12 items - Ironing Service 11 Mar 2009 to 10 Apr 2009')
date_pat regexp에 문자열을 나눕니다. 경기는 반환 된 목록에 포함됩니다. 따라서 우리는 다음을 얻습니다.
['12 items - Ironing Service ', '11 Mar 2009 to 10 Apr 2009', '']
map(string.strip,date_pat.split(line)[:2])
결과를 예열합니다.
만약에 line
일치하지 않습니다 date_pat
, 그 다음에 date_pat.split(line)
보고 [line,]
, 그래서
description,period=map(string.strip,date_pat.split(line)[:2])
하나의 요소 만 2 튜플로 목록을 풀 수 없기 때문에 ValueError를 올립니다. 우리는이 예외를 포착하지만 단순히 다음 줄로 전달합니다.