2009-07-31 11 views
15

En utilisant Ruby, comment puis-je utiliser une seule regex pour correspondre à toutes les occurrences de 'y' dans "xy y ay xy + y" qui ne sont pas précédées de x (y, ay, + y)?
/[^ x] y/correspond au caractère précédent, donc je besoin d'une alternative ...regexp pour faire correspondre string1 sauf précédé par string2

+0

J'allais suggérer un regard en arrière négatif, mais il semble que vous êtes hors de la chance sur ce point: http://www.regular-expressions.info /lookaround.html#limitbehind. * "Enfin, les saveurs comme JavaScript, Ruby et Tcl ne supportent pas du tout lookbehind, même si elles supportent lookahead." * –

+0

Voir aussi http://stackoverflow.com/questions/530441/how-would-you-use- a-regular-expression-to-ignore-string-that-contain-a-specific – finnw

+0

Si les assertions look-behind ne sont pas supportées, on peut utiliser ceci: '([^ x] y") | (^ y ")' . 'y' peut apparaître au début de la chaîne et ce cas n'est pas couvert par '/ [^ x] y /'. – approxiblue

Répondre

34

Vous avez besoin d'une assertion avec rétroaction négative de largeur nulle. Essayez /(?<!x)y/ qui indique exactement ce que vous recherchez, c'est-à-dire trouvez tout 'y' non précédé de 'x', mais n'inclut pas le caractère précédent, qui est la partie de largeur nulle.

Edité pour ajouter: Apparemment, ceci n'est supporté que par Ruby 1.9 et plus.

-1

En PCRE, vous utilisez un look derrière négatif:

(:<!x)y 

Je ne sais pas si cela est soutenu par Ruby, mais vous pouvez toujours chercher.

-1

Il peut être fait avec un regard négatif derrière, (?<!x)y

2

Ruby ne supporte pas malheureusement lookbehind négatif, alors vous aurez du mal si vous avez besoin de chercher plus d'un seul caractère. Pour un seul caractère, vous pouvez prendre soin de ce en capturant le match:

/[^x](y)/ 
+0

Ah, je ne suis pas un expert de Ruby - jbourque dit que lookbehind négatif est dans Ruby plus récent. Il y a ta vraie réponse. – Cascabel

+0

[^ x] doit correspondre à un caractère. si y se trouve au début de la ligne, nous devrions le faire correspondre:/(?: \ A |^| [^ x]) y / –

3

regarder en arrière négatif est pas prise en charge jusqu'à Ruby 1.9, mais vous pouvez faire quelque chose de similaire en utilisant scan:

"xy y ay xy +y".scan(/([^x])(y)/) # => [[" ", "y"], ["a", "y"], ["+", "y"]] 
"xy y ay xy +y".scan(/([^x])(y)/).map {|match| match[1]} # => ["y", "y", "y"] 

Bien sûr, c'est beaucoup plus difficile si vous voulez éviter beaucoup plus qu'un seul caractère avant le y. Ensuite, vous auriez à faire quelque chose comme:

"abby y crabby bally +y".scan(/(.*?)(y)/).reject {|str| str[0] =~ /ab/} # => [[" ", "y"], [" ball", "y"], [" +", "y"]] 
"abby y crabby bally +y".scan(/(.*?)(y)/).reject {|str| str[0] =~ /ab/}.map {|match| match[1]} # => ["y", "y" "y"] 
Questions connexes