2009-07-03 5 views
0

D'accord, celui-ci est intéressant. J'ai une solution, mais je ne l'aime pas.Expression régulière optimale: correspond à des ensembles de lignes commençant par

Le but est de pouvoir trouver un ensemble de lignes commençant par 3 périodes - pas une ligne individuelle, mais une collection de toutes les lignes d'une ligne qui correspondent. Par exemple, voici quelques matchs (chaque match est séparé par une ligne blanche):

... 

...hello 

... 
...hello 
...world 
... 
...wazzup? 
... 

Ma solution est la suivante:

^\.\.\..*(\n\.\.\..*)*$ 

Il correspond à tous ceux-ci, il est donc ce que j'utilise pour maintenant - cependant, il semble assez idiot de répéter le motif \.\.\..*. Y a-t-il un moyen plus simple?

S'il vous plaît test your regex avant de le soumettre, plutôt que de soumettre ce qui "devrait fonctionner". Par exemple, j'ai essayé la suite de la première:

(^\.\.\..*$)+ 

qui ne revint lignes individuelles, même si dans mon esprit il semble que ça ferait l'affaire - je suppose que je ne comprends pas internals regex. (Et non, je n'avais pas besoin de mettre des drapeaux pour que^et $ correspondent aux limites des lignes, puisque j'implémente ceci dans Ruby.)

Donc je ne suis pas totalement sûr qu'il y ait une bonne réponse, mais on serait très apprécié - merci d'avance!

+0

vous devez spécifier la langue que vous utilisez car tout le monde a fait une implémentation différente. .NET? Perl? javascript? – Eric

+5

Juste pour dire que j'utiliserais probablement juste le code normal; la plupart des langues facilitent la lecture ligne par ligne d'un fichier (etc) et vérifient qu'une chaîne commence par quelques caractères ... –

+2

Je suis presque sûre d'avoir spécifié Ruby là-dedans ... non? – Matchu

Répondre

1

Dans la plupart des implémentations regex, vous pouvez raccourcir \.\.\. en utilisant \.{3} pour que votre solution devienne \.{3}.*(\n\.{3}.*)*.

+0

Semble même attraper des lignes vides, bien que = /: http: //regexpal.com/? Flags = m & regex = ^% 28 \ n * \. {3}. *% 29 *% 24 & input = ... si% 20all% 20 %% 20%% 20yellow% 0A% 0A ...% 0A ... ils% 27re% 20part% 20of% 20the% 20same% 20match% 0A ...% 0A% 0A% 0A% 0A ... lequel% 20isn% 27t% 20desired% 20behavior% 20-% 20darn! – Matchu

+0

Mais j'apprécie le raccourcissement - c'est la première étape: D – Matchu

+0

Je n'avais pas entièrement saisi vos besoins jusqu'à présent, désolé. Je ne peux pas penser à une solution plus courte alors j'ai édité ma réponse en conséquence. –

1

Ce que vous avez déjà est déjà simple et compréhensible. Gardez à l'esprit que plus de RegExps "intelligents" peuvent très bien être plus lents et sans doute moins lisibles.

lignes supposant sont terminées par un \n:

((^|\n)\.{3}[^\n]*)+ 

Je ne suis pas familier avec Ruby, donc en fonction de la façon dont il retourne correspond vous pourriez avoir besoin de groupes « non-appariement »:

((?:(?:^|\n)\.{3}[^\n]*)+) 
+0

Excellent point: certains benchmarks ont montré que cette regex plus comprimée se déroulait à environ deux tiers de la vitesse. Je ne suis pas sûr, alors, ce que je fais maintenant en ce qui concerne cette question ... Je suppose que je vais juste marquer l'autre puisque c'est le seul raccourcissement que je peux vraiment me sentir à l'aise - même si je suis déçu réponse "simple" Merci! – Matchu

0

Vous sont assez proches d'une solution avec (^\.\.\..*$)+, mais comme le modificateur + se trouve à l'extérieur du groupe, il est écrasé à chaque fois et il ne reste que la dernière ligne. Essayez de l'emballer dans un groupe externe: ((^\.\.\..*$)+) et en regardant le premier submatch et en ignorant le premier.

combiné avec l'autre suggestion: ((^\.{3}.*$)+)

+0

Je dis ignorer l'interne parce que vous n'aimiez pas la complexité accrue dans la réponse de Borgar. Vous pouvez ne pas faire correspondre le groupe interne pour l'ignorer: ((?:^\. {3}. * $) +) –

+0

Heureusement, je ne suis pas concerné par le regroupement dans ce cas. Je n'ai pas besoin de submatches. J'ai juste besoin des allumettes que je vais remplacer dans l'ordre :) Donc le groupement n'était pas le problème avec cette solution. Il ne faisait tout simplement pas les bons matchs. – Matchu

+0

Donc, je suis satisfait en l'état. Mais merci pour l'aide! – Matchu

1
^([.]{3}.*$\n?)+ 

Cela n'a pas vraiment besoin $ là-dedans.

+0

Que fait le $ au milieu du motif? – FMc

+0

'$' correspond à la fin d'une ligne ou à la fin de la chaîne entière. Si c'est la fin d'une ligne, '\ n?' consomme le saut de ligne afin que la correspondance puisse continuer sur la ligne suivante. Donc, le '$' au milieu de l'expression rationnelle fait son poids, mais celui à la fin est redondant. –

+0

Peut-être qu'il me manque quelque chose, mais je pense que la gourmandise des expressions régulières assurera que les lignes entières sont consommées, donc les deux caractères $ peuvent être supprimés du motif:/^([.]{3}.*\n?) + / – FMc

Questions connexes