Comment puis-je corriger mon regex pour ne pas correspondre trop avec un quantificateur gourmand? [dupliquer]

StackOverflow https://stackoverflow.com/questions/255815

Question

    

Cette question a déjà une réponse ici:

         

J'ai la ligne suivante:

"14:48 say;0ed673079715c343281355c2a1fde843;2;laka;hello ;)"

J'analyse ceci en utilisant une expression rationnelle simple:

if($line =~ /(\d+:\d+)\ssay;(.*);(.*);(.*);(.*)/) {
    my($ts, $hash, $pid, $handle, $quote) = ($1, $2, $3, $4, $5);
}

Mais le; à la fin, ça dérange et je ne sais pas pourquoi. L’opérateur avide ne devrait-il pas gérer "tout"?

Était-ce utile?

La solution

L'opérateur avide essaie de saisir autant de choses que possible et continue de faire correspondre la chaîne. Ce qui se passe est le premier (après "dire") saisit "0ed673079715c343281355c2a1fde843; 2", le second prend "laka", le troisième trouve "bonjour". et le quatrième correspond à la parenthèse.

Ce que vous devez faire est de rendre tout sauf le dernier non-glouton, afin d’attraper le moins possible et de faire correspondre la chaîne:

(\d+:\d+)\ssay;(.*?);(.*?);(.*?);(.*)

Autres conseils

(\d+:\d+)\ssay;([^;]*);([^;]*);([^;]*);(.*)

devrait mieux fonctionner

Même si une expression rationnelle peut facilement le faire, je ne suis pas sûr que ce soit l'approche la plus directe. C'est probablement le plus court, mais cela ne le rend pas réellement le plus facile à maintenir.

Au lieu de cela, je suggérerais quelque chose comme ceci:

$x="14:48 say;0ed673079715c343281355c2a1fde843;2;laka;hello ;)";

if (($ts,$rest) = $x =~ /(\d+:\d+)\s+(.*)/)
{
    my($command,$hash,$pid,$handle,$quote) = split /;/, $rest, 5;
    print join ",", map { "[

Même si une expression rationnelle peut facilement le faire, je ne suis pas sûr que ce soit l'approche la plus directe. C'est probablement le plus court, mais cela ne le rend pas réellement le plus facile à maintenir.

Au lieu de cela, je suggérerais quelque chose comme ceci:

[14:48],[say],[0ed673079715c343281355c2a1fde843],[2],[laka],[hello ;)]

Cela se traduit par:

<*>

Je pense que ceci est juste un peu plus lisible. Non seulement cela, je pense qu'il est également plus facile de déboguer et de maintenir, car c'est plus proche de la façon dont vous le feriez si un humain essayait la même chose avec un stylo et du papier. Découpez la chaîne en morceaux que vous pouvez ensuite analyser plus facilement - demandez à l'ordinateur de faire exactement ce que vous feriez. Lorsque le temps sera venu d’apporter des modifications, je pense que celui-ci sera mieux loti. YMMV.

]" } $ts,$command,$hash,$pid,$handle,$quote }

Cela se traduit par:

<*>

Je pense que ceci est juste un peu plus lisible. Non seulement cela, je pense qu'il est également plus facile de déboguer et de maintenir, car c'est plus proche de la façon dont vous le feriez si un humain essayait la même chose avec un stylo et du papier. Découpez la chaîne en morceaux que vous pouvez ensuite analyser plus facilement - demandez à l'ordinateur de faire exactement ce que vous feriez. Lorsque le temps sera venu d’apporter des modifications, je pense que celui-ci sera mieux loti. YMMV.

Essayez de créer les 3 premiers (. *) ungreedy (. *?)

Si les valeurs de votre liste délimitée par des points-virgules ne peuvent pas inclure de points-virgules eux-mêmes, vous obtiendrez l'expression régulière la plus efficace et la plus simple en l'épelant simplement. Si certaines valeurs ne peuvent être que, par exemple, une chaîne de caractères hexadécimaux, épelez-les. Les solutions utilisant un point paresseux ou gourmand entraîneront toujours beaucoup de retours en arrière inutiles lorsque l'expression régulière ne correspond pas à la chaîne de sujet.

(\d+:\d+)\ssay;([a-f0-9]+);(\d+);(\w+);([^;\r\n]+)

Vous pouvez faire un * non-gourmand en ajoutant un point d'interrogation:

$line =~ /(\d+:\d+)\ssay;(.*?);(.*?);(.*?);(.*)/

ou vous pouvez faire correspondre tout sauf un point-virgule dans chaque partie sauf la dernière:

$line =~ /(\d+:\d+)\ssay;([^;]*);([^;]*);([^;]*);(.*)/
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top