Comment écrire la grammaire pour cela dans pyparsing: faire correspondre un ensemble de mots mais ne contenant pas un motif donné

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

  •  05-07-2019
  •  | 
  •  

Question

Je suis nouveau sur Python et pyparsing. Je dois accomplir les tâches suivantes.

Mon exemple de ligne de texte est le suivant:

12 items - Ironing Service    11 Mar 2009 to 10 Apr 2009
Washing service (3 Shirt)  23 Mar 2009

Je dois extraire la description de l'article, période

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

Comment faire cela?

Était-ce utile?

La solution

Je suggérerais de regarder SkipTo comme la classe pyparse la plus appropriée, car vous avez une bonne définition du texte non souhaité , mais accepterez à peu près n'importe quoi avant. Voici deux manières d'utiliser 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

Les deux boucles pour affichent les éléments suivants:

12 items - Ironing Service    
Washing service (3 Shirt) 

Autres conseils

M K Saravanan, ce problème d’analyse syntaxique n’est pas si difficile à résoudre avec du bien

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

donne

# ('12 items - Ironing Service', '11 Mar 2009 to 10 Apr 2009')
# ('Washing service (3 Shirt)', '23 Mar 2009')

Le principal bourreau de travail ici est bien sûr le motif récurrent. Brisons-le:

\ d {1,2} \ s + [a-zA-Z] {3} \ s + \ d {4} est l'expression rationnelle pour une date, l'équivalent de tok_date_in_ddmmmyyyy . \ d {1,2} correspond à un ou deux chiffres, \ s + correspond à un ou plusieurs espaces, [a-zA-Z] {3} correspond à 3 lettres, etc.

(?: \ s + à \ s + \ d {1,2} \ s + [a-zA-Z] {3} \ s + \ d {4})? est une expression rationnelle entouré de (?: ...) . Ceci indique une expression rationnelle non-groupante. En utilisant cela, aucun groupe (par exemple match.group (2)) n’est affecté à cette expression rationnelle. Ceci est important car date_pat.split () retourne une liste avec chaque groupe étant membre de la liste. En supprimant le regroupement, nous conservons la période entière du 11 mars 2009 au 10 avril 2009 . Le point d'interrogation à la fin indique que ce motif peut se produire zéro ou une fois. Cela permet à l'expression rationnelle de correspondre à la fois 23 mars 2009 et du 11 mars 2009 au 10 avril 2009 .

text.splitlines () divise le texte sur \ n .

date_pat.split ('12 éléments - Service de repassage du 11 mars 2009 au 10 avril 2009 ')

divise la chaîne sur l'expression rationnelle date_pat. La correspondance est incluse dans la liste renvoyée. Nous obtenons ainsi:

['12 éléments - Service de repassage', 'du 11 mars 2009 au 10 avril 2009', '']

map (string.strip, date_pat.split (line) [: 2]) rend le résultat agréable.

Si ligne ne correspond pas à date_pat , date_pat.split (ligne) renvoie [ligne,] . , alors

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

déclenche une ValueError car nous ne pouvons pas décompresser une liste avec un seul élément dans un 2 -uple. Nous attrapons cette exception mais passons simplement à la ligne suivante.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top