pyparsing에서 이것에 대한 문법을 ​​작성하는 방법 : 단어 세트와 일치하지만 주어진 패턴을 포함하지 않습니다.

StackOverflow https://stackoverflow.com/questions/1805309

  •  05-07-2019
  •  | 
  •  

문제

나는 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를 올립니다. 우리는이 예외를 포착하지만 단순히 다음 줄로 전달합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top