116 votes

Ma regex correspond à trop de choses. Comment faire pour qu'elle s'arrête ?

J'ai une corde gigantesque et laide :

J0000000: Transaction A0001401 started on 8/22/2008 9:49:29 AM
J0000010: Project name: E:\foo.pf
J0000011: Job name: MBiek Direct Mail Test
J0000020: Document 1 - Completed successfully

J'essaie d'en extraire des morceaux à l'aide d'une expression rationnelle. Dans ce cas, je veux extraire tout ce qui se trouve après Project Name jusqu'à la partie où il est dit J0000011: (le chiffre 11 sera différent à chaque fois).

Voici l'expression rationnelle avec laquelle j'ai joué :

Project name:\s+(.*)\s+J[0-9]{7}:

Le problème, c'est qu'il ne s'arrête pas avant d'avoir touché le J0000020 : à la fin.

Comment faire en sorte que l'expression rationnelle s'arrête à la première occurrence de J[0-9]{7} ?

178voto

jj33 Points 3858

Faire .* non avide en ajoutant ? ' après lui :

Project name:\s+(.*?)\s+J[0-9]{7}:

15voto

Konrad Rudolph Points 231505

L'utilisation de quantificateurs non gourmands est probablement la meilleure solution, notamment parce qu'elle est plus efficace que l'alternative gourmande : Les correspondances avides vont généralement aussi loin qu'elles le peuvent (ici, jusqu'à la fin du texte !) et remontent ensuite caractère après caractère pour essayer de correspondre à la partie qui suit.

Cependant, il est préférable d'utiliser une classe de caractères négatifs :

Project name:\s+(\S*)\s+J[0-9]{7}:

\S signifie "tout sauf un espace et c'est exactement ce que vous voulez.

7voto

Svend Points 3291

Bien, ".*" est un sélecteur avide. Vous le rendez non avide en utilisant ".*?" Dans ce dernier cas, le moteur d'expressions rationnelles fera correspondre, à chaque étape, le texte dans le champ "." tente de correspondre à la marque qui suit le ".*?" . Cela signifie que si, par exemple, rien ne vient après l'élément ".*?" alors il n'y a pas de correspondance.

Voici ce que j'ai utilisé. s contient votre chaîne de caractères originale. Ce code est spécifique à .NET, mais la plupart des variantes de regex ont quelque chose de similaire.

string m = Regex.Match(s, @"Project name: (?<name>.*?) J\d+").Groups["name"].Value;

1voto

Hershi Points 1228

Je vous recommande également d'expérimenter les expressions régulières à l'aide d'"Expresso" - c'est un excellent (et gratuit) utilitaire pour l'édition et le test des expressions régulières.

L'un de ses avantages est que son interface utilisateur expose de nombreuses fonctionnalités de regex que les personnes n'ayant pas l'expérience des regex ne connaissent pas forcément, de manière à ce qu'il leur soit facile d'apprendre ces nouveaux concepts.

Par exemple, lorsque vous construisez votre regex à l'aide de l'interface utilisateur et que vous choisissez "*", vous avez la possibilité de cocher la case "Aussi peu que possible" et de voir la regex résultante, ainsi que de tester son comportement, même si vous n'étiez pas familier avec les expressions non gourmandes auparavant.

Disponible en téléchargement sur leur site : http://www.ultrapico.com/Expresso.htm

Téléchargement express : http://www.ultrapico.com/ExpressoDownload.htm

0voto

Shailendra Points 181

(Nom du projet : \s +[A-Z] :(? : \\w +)+.[a-zA-Z]+ \s +J[0-9]{7})(?= :)

Cela fonctionnera pour vous.

Ajout (? : \\w +)+.[a-zA-Z]+ sera plus restrictif que .*.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X