2010-09-30 14 views
3

J'ai une expression régulière qui fonctionne, mais je voudrais la rendre un peu plus lisible, et je suis loin d'être un gourou de la regex, alors j'espérais humblement quelques conseils.Rendre une petite expression régulière un peu plus lisible

Ceci est conçu pour extraire la sortie de plusieurs compilateurs différents, des lieurs et d'autres outils de construction, et est utilisé pour construire un joli petit rapport estival. Ça fait du boulot génial, mais je me sens comme si je l'avais écrit d'une manière maladroite, et j'apprendrais plutôt que de le garder dans le mauvais sens.

(.*?)\s?:?\s?(informational|warning|error|fatal error)?\s([A-Z]+[0-9][0-9][0-9][0-9]):\s(.*)$ 

qui, décomposé simplement, est la suivante:

(.*?)          # non-greedily match up until... 
\s?:?\s?         # we come across a possible " : " 
(informational|warning|error|fatal error)? # possibly followed by one of these 
\s([A-Z]+[0-9][0-9][0-9][0-9]):\s   # but 100% followed by this alphanum 
(.*)$          # and then capture the rest 

Je suis surtout intéressé à faire la 2ème et 4ème entrée au-dessus ... plus belle. Pour une raison quelconque, le testeur de regex que j'utilisais (The Regulator) ne correspondait pas aux espaces, donc j'ai dû utiliser le \ s ... mais il n'est pas fait pour correspondre à d'autres espaces.

Toute scolarité sera grandement appréciée.

+2

Pouvez-vous utiliser « beau » et « regex » dans la même phrase? –

+2

Dans quel langage de programmation utilisez-vous la regex? –

Répondre

2

Ligne 2

Je pense que l'expression régulière ne correspond pas avec le commentaire.Vous voulez sans doute ceci:

(\s:\s)? 

Pour le rendre non-capture:

(?:\s:\s)? 

Vous devriez pouvoir utiliser un espace littéral au lieu de \s. Cela doit être une restriction dans l'outil que vous utilisez.

Ligne 4

[0-9][0-9][0-9][0-9] peut être remplacé par [0-9]{4}. Dans certaines langues, [0-9] est équivalent à \d.

+0

J'aime le bit non-capturant ... sur une note de côté, est-il possible de mandater un de ces deux groupes optionnels ? c'est-à-dire, l'un ou l'autre ou les deux, mais pas non plus? – Nate

+0

@Nate: Je pense que c'est la meilleure façon de faire cela: '((information | avertissement | erreur | erreur fatale) (\ s: \ s)? | \ S: \ s)' –

4

La meilleure façon de faire une longue regex plus lisible est d'utiliser le « free-spacing » (ou \x) modifier, qui vous permettra d'écrire votre regex comme vous l'avez fait dans le deuxième bloc de code - il fait des espaces ignorés . Ceci n'est cependant pas supporté par tous les moteurs (selon la page ci-dessus, .NET, Java, Perl, PCRE, Python, Ruby et XPath le supportent).

Notez également que en mode sans espacement, vous pouvez utiliser [ ] au lieu de \s si vous voulez faire correspondre uniquement un espace (sauf si vous utilisez Java, auquel cas vous devez utiliser , qui est échappé espace).

Il n'y a pas vraiment tout ce que vous pouvez faire pour la deuxième ligne, si vous voulez que chaque élément soit en option indépendamment des autres éléments, mais le quatrième peut être raccourci:

\s([A-Z]+\d{4}):\s 

\d est un shorthand class équivalent à [0-9], et {4} précise qu'il devrait apparaître exactly four times.

La troisième ligne peut être légèrement raccourcie et ((?:…) spécifie une non-capturegroup):

(informational|warning|(?:fatal)? error)? 

D'un point de vue de l'efficacité, à moins que vous avez réellement besoin de capturer des sous-modèles chaque fois que vous utilisez entre parenthèses, vous pouvez tous les supprimer, sauf sur la troisième ligne, où le groupe est nécessaire pour le alternation) - mais celui-ci peut être rendu non-capture. Mettre tout cela ensemble, vous obtiendrez:

.*? 
\s?:?\s? 
(?:informational|warning|(?:fatal)?error)? 
\s[A-Z]+\d{4}:\s 
.*$ 
+0

Je suis à bord du \ x ... même si je ne l'ai pas utilisé ici (après avoir découvert \ x oh ... hier :). Je suis plus intéressé s'il y a vraiment une meilleure syntaxe regex à utiliser que ce que j'ai utilisé pour les lignes 2 et 4 – Nate

0

Peut-être que vous pouvez construire le RE des sous-expressions, de sorte que votre RE final ressemblerait à quelque chose comme ceci:

/$preamble$possible_colon$keyword$alphanum$trailer/