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)
他のヒント
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タプルにアンパックできないためです。この例外をキャッチしますが、単に次の行に渡します。