كيفية كتابة النحوي لهذا في pyparsing: مطابقة مجموعة من الكلمات ولكن لا تحتوي على نمط معين

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

  •  05-07-2019
  •  | 
  •  

سؤال

وأنا جديدة على بيثون و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 سارافانان، هذه المشكلة الاعراب معينة ليس من الصعب جدا القيام به مع الجيدة "إعادة أوله:

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} هو التعبير العادي لتحديد موعد، أي ما يعادل 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})? هو التعبير العادي محاطة (?:...). وهذا يدل على التعبير العادي غير التجمع. باستخدام هذا، لا توجد مجموعة (على سبيل المثال match.group (2)) تم تعيينه لهذا التعبير العادي. وهذا أمر مهم لأن date_pat.split () بإرجاع قائمة مع كل مجموعة كونها عضوا في القائمة. من خلال قمع التجمع، علينا أن نحافظ على 11 Mar 2009 to 10 Apr 2009 فترة بأكمله معا. علامة الاستفهام في نهاية تشير إلى أن هذا النمط قد تحدث الصفر أو مرة واحدة. وهذا يسمح التعبير العادي لمباراة سواء 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. يتم تضمين المباراة في القائمة التي تم إرجاعها. وهكذا نحصل على:

و['12 items - Ironing Service ', '11 Mar 2009 to 10 Apr 2009', '']

وmap(string.strip,date_pat.split(line)[:2]) prettifies النتيجة.

إذا لا تتطابق line date_pat، ثم date_pat.split(line) عوائد [line,]، لذلك

وdescription,period=map(string.strip,date_pat.split(line)[:2])

ويثير ValueError لأننا لا نستطيع فك قائمة مع عنصر واحد فقط في 2-الصفوف (tuple). ضبطنا هذا الاستثناء ولكن ببساطة تمرير إلى السطر التالي.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top