2017-03-24 1 views
2

Je suis en train d'écrire une fonction parse telle que, par exemple,pyparsing, comment arrêter un Regex de consommer toute la chaîne

assert parse("file://foo:bar.txt:r+") == ("foo:bar.txt", "r+") 

La chaîne se compose d'un préfixe fixe file://, suivi d'un nom de fichier (qui peut être constitué d'un ou de plusieurs caractères), suivi d'un deux-points et d'une chaîne représentant les indicateurs d'accès.

Voici une mise en œuvre en utilisant des expressions régulières:

import re 

def parse(string): 
    SCHEME = r"file://"        # File prefix 
    PATH_PATTERN = r"(?P<path>.+)"     # One or more of any character 
    FLAGS_PATTERN = r"(?P<flags>[rwab+0-9]+)"  # The letters r, w, a, b, a '+' symbol, or any digit 

    FILE_RESOURCE_PATTERN = SCHEME + PATH_PATTERN + r":" + FLAGS_PATTERN + r"$"  # The full pattern including the end of line character 

    tokens = re.match(FILE_RESOURCE_PATTERN, string).groupdict() 
    return tokens['path'], tokens['flags'] 

Je préférerais utiliser PyParsing, cependant, car il donne généralement des messages d'erreur plus détaillés si la chaîne ne correspond pas à l'expression (plutôt que re.match qui retourne simplement None), et je voudrais éventuellement rendre le flags optionnel.

Après la réponse de Paul McGuire dans python regex in pyparsing, je fait la tentative suivante:

from pyparsing import Word, alphas, nums, StringEnd, Regex, FollowedBy, Suppress, Literal 

def parse(string): 
    scheme = Literal("file://") 
    path = Regex(".+") 
    flags = Word(alphas + nums + "+") 

    expression = Suppress(scheme) + (~(Suppress(":") + flags + StringEnd()) + path("path") + Suppress(":") + flags("flags") + StringEnd()) 

    tokens = expression.parseString(string) 
    return tokens['path'], tokens['flags'] 

Dans la deuxième partie de l'expression, je suis en train essentiellement le négatif (~suffix + path + suffix) préanalyse, où suffix est ":" + flags + StringEnd(). Cependant, lorsque vous essayez d'analyser "file://foo:bar.txt:r+", je lance dans l'erreur suivante:

pyparsing.ParseException: Expected ":" (at char 21), (line:1, col:22) 

Depuis la chaîne est de 21 caractères, j'interprète cela comme le Regex a « consommé » toute la chaîne de sorte que le suffixe est pas plus "trouvé".

Comment puis-je corriger la méthode parse en utilisant pyparsing?

+1

Dans votre solution re, le moteur re peut faire préanalyse et retours en arrière pour trouver le « : », mais pyparsing, la re dans le Regex ne connaît pas les éléments suivants Supprimer (':') l'expression. Essayez de changer 'path' en' Regex (r "[^:] +") ', qui consommera tout sauf ':' s. – PaulMcG

+0

[Paul McGuire] (http://stackoverflow.com/users/165216/paul-mcguire), en fait le 'chemin' peut contenir des deux-points (': 's), comme dans l'exemple, où il est' foo: bar .txt'. Donc, omettre des deux-points de 'Regex' ne ferait pas. –

Répondre

0

Essayez ceci:

s="file://foo:bar.txt:r+" 
path,flag=re.sub(r'.*\/\/(.*):(.*$)',r'\1,\2',s)