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) 

他のヒント

M Kサラバナン、この特定の解析の問題は、良い 'ole 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')

ここでの主な主力は、もちろんreパターンです。それをバラバラにしましょう:

\ d {1,2} \ s + [a-zA-Z] {3} \ s + \ d {4} は日付の正規表現で、 tok_date_in_ddmmmyyyyと同等 \ d {1,2} は1桁または2桁に一致し、 \ s + は1つ以上の空白に一致します、 [a-zA-Z] {3} は3文字などに一致します。

(?:\ s + to \ s + \ d {1,2} \ s + [a-zA-Z] {3} \ s + \ d {4})?は正規表現です(?:...)で囲まれています。 これは、グループ化されていない正規表現を示します。これを使用すると、この正規表現にグループ(たとえば、match.group(2))は割り当てられません。これは、date_pat.split()が各グループがリストのメンバーであるリストを返すため重要です。グループ化を抑制することで、期間 2009年3月11日から2009年4月10日をまとめます。最後の疑問符は、このパターンがゼロまたは1回発生する可能性があることを示します。これにより、正規表現が両方に一致するようになります 2009年3月23日および 2009年3月11日から2009年4月10日

text.splitlines()は、 \ n でテキストを分割します。

date_pat.split('12 items-Ironing Service 2009年3月11日から2009年4月10日まで)

date_pat正規表現で文字列を分割します。一致は返されたリストに含まれます。 したがって、次のようになります。

['12 items-Ironing Service'、 '2009年3月11日から2009年4月10日'、 '']

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])

ValueErrorが発生するのは、要素を1つだけ含むリストを2タプルにアンパックできないためです。この例外をキャッチしますが、単に次の行に渡します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top