2008-10-08 8 views
0

Je possède ce regex .NET:Regex ne le droit parens

^(?<prefix>("[^"]*"))\s(?<attrgroup>(\([^\)]*\)))\s(?<suffix>("[^"]*"))$ 

Il correspond bien aux chaînes suivantes:

"some prefix" ("attribute 1" "value 1") "some suffix" 
"some prefix" ("attribute 1" "value 1" "attribute 2" "value 2") "some suffix" 

Il échoue sur ...

"some prefix" ("attribute 1" "value (fail) 1") "some suffix" 

. ..due à la droite paren après "échouer".

Comment puis-je modifier mon expression régulière afin que le groupe de correspondance attrgroup contienne "("attribute 1" "value (fail) 1")"? Je l'ai regardé pendant trop longtemps et ai besoin de quelques yeux frais. Merci!

Édition:attrgroup ne contiendra jamais autre chose que des paires de chaînes entre guillemets.

+0

Par votre spécification d'entrée, 'attrgroup' contient-il autre chose que des chaînes entre guillemets? –

+0

Bonne question! La réponse est non, ce n'est pas le cas, et ils viennent toujours par deux. –

Répondre

2

ma, devinez non testé:

^(?<prefix>("[^"]*"))\s(?<attrgroup>(\(("[^"]*")(\s("[^"]*")*)**\)))\s(?<suffix>("[^"]*"))$ 

par la présente que j'ai remplacé

[^\)]* 

avec

("[^"]*")(\s("[^"]*")*)* 

Je supposais tout ce qui entre parenthèses est soit entre guillemets doubles, ou un espace.

Si vous voulez savoir comment je suis arrivé avec cela, lisez Mastering Regular Expressions.

ps.Si je me trompe, cela validera également le groupe d'attributs en tant que paires de chaînes entre guillemets.

1
^(?<prefix>"[^"]*")\s+(?<attrgroup>\(.*\))\s+(?<suffix>"[^"]*")$ 

l'a corrigé pour moi. J'ai supprimé les groupes non nommés superflus et simplifié (jusqu'à "n'importe quel caractère") le groupe d'attributs.

Un très investissement rentable serait JG RegexBuddy Soft

Edit: Cela ne validera pas le groupe d'attributs sous forme de paires de chaînes entre guillemets, mais cela ne devrait/pourrait être fait dans un regex séparé/étape de validation.

0

La solution Hometoasts est une bonne solution, bien que, comme toute regex libérale, elle ne doit être utilisée que pour extraire des données de sources dont vous avez une assurance raisonnable qu'elles sont bien formées et non pour validation.

0

Sans aborder les spécificités de cette expression régulière, je recommanderais d'utiliser un outil Regex pour aider à construire, tester et valider vos expressions régulières. Pour tout ce qui n'est pas trivial, ou les expressions que vous pourriez avoir besoin de maintenir/mettre à jour, ces types d'outils sont essentiels.

vous recommandons ...

The Regex Coach - écrit en Lisp, un peu plus, mais je préfère vraiment celui-ci à d'autres.

Rad Software Regex Designer - .NET et plus "moderne" peut-être. Certains peuvent aimer celui-ci.

0

Je suggère d'utiliser un analyseur capable de gérer de telles structures. L'expression régulière échoue, et c'est correct, car la langue que vous essayez d'analyser n'a pas l'air régulière - du moins à partir des exemples donnés ci-dessus. Chaque fois que vous avez besoin de reconnaître l'imbrication, les expressions rationnelles échoueront ou deviendront des bêtes compliquées comme celle ci-dessus. Même si la langue est régulière, cette expression régulière semble trop compliquée pour moi. Je préfère utiliser quelque chose comme ceci:

def parse_String(string): 
    index = skip_spaces(string, 0) 
    index, prefix = read_prefix(string, index) 
    index = skip_spaces(string, index) 
    index, attrgroup = read_attrgroup(string, index) 
    index = skip_spaces(string, index) 
    index, suffix = read_suffix(string, index) 
    return prefix, attrgroup, suffix 

def read_prefix(string, start_index): 
    return read_quoted_string(string, start_index) 

def read_attrgroup(string, start_index): 
    end_index, content = read_paren(string, start_index) 

    index = skip_spaces(content, 0) 
    index, first_entry = read_quoted_string(content, index) 
    index = skip_spaces(content, index) 
    index, second_entry = read_quoted_string(content, index) 
    return end_index, (first_entry, second_entry) 


def read_suffix(string, start_index): 
    return read_quoted_string(string, start_index) 

def read_paren(string, start_index): 
    return read_delimited_string(string, start_index, '(', ')') 

def read_quoted_string(string, start_index): 
    return read_delimited_string(string, start_index, '"', '"') 

def read_delimited_string(string, starting_index, start_limiter, end_limiter): 
    assert string[starting_index] == start_limiter, (start_limiter 
                +"!=" 
                +string[starting_index]) 
    current_index = starting_index+1 
    content = "" 
    while(string[current_index] != end_limiter): 
     content += string[current_index] 
     current_index += 1 

    assert string[current_index] == end_limiter 
    return current_index+1, content 

def skip_spaces(string, index): 
    while string[index] == " ": 
     index += 1 
    return index 

oui, c'est plus de code, et oui, par le nombre brut de clés, cela a pris plus de temps. Cependant - au moins pour moi - ma solution est beaucoup plus facile à vérifier. Cela augmente encore plus si vous supprimez un tas de la plomberie string-and-index en déplaçant tout cela dans la classe, qui analyse ces chaînes dans son constructeur. De plus, il est facile de rendre l'espacement d'espace implicite (en utilisant une méthode magique next-char qui saute juste les caractères jusqu'à ce qu'un non-espace apparaisse, à moins qu'il ne soit dans un mode non-skip dû aux chaînes. la fonction délimitée, par exemple). Cela transformerait la chaîne parse_ en:

def parse_string(string): 
    prefix = read_prefix() 
    attrgroup = read_attr_group() 
    suffix = read_suffix() 
    return prefix, attrgroup, suffix. 

De plus, ces fonctions peuvent être étendues plus facilement pour couvrir des expressions plus compliquées. Attrgroups arbitrairement imbriqués? un changement d'une ligne de code. Parens imbriquées? un peu plus de travail, mais pas de réel problème.

Maintenant, s'il te plaît, flamboie-moi et abats-moi pour être un hérétique et un parseur-plaideur. > :)

PS: oui, ce code n'a pas été testé. comme je me connais, il y a 3 fautes de frappe là-dedans je n'ai pas vu.

Questions connexes