2009-07-31 8 views
15

Używając Ruby, w jaki sposób mogę użyć pojedynczego wyrażenia regularnego do dopasowania wszystkich wystąpień "y" w "xy yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy)" y)?
/[^ x] y/dopasowuje poprzedni charakter zbyt, więc muszę mieć alternatywę ...regexp, aby dopasować ciąg1, chyba że poprzedzi go ciąg2

+0

Miałem zamiar zaproponować negatywny lookbehind, ale wygląda na to, że nie masz szczęścia na ten wynik: http://www.regular-expressions.info /lookaround.html#limitbehind. * "Wreszcie, smaki takie jak JavaScript, Ruby i Tcl nie obsługują w ogóle lookbehind, nawet jeśli obsługują uprzedzenie". * –

+0

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

+0

Jeśli asercje nie są obsługiwane, możemy użyć tego: '([^ x] y") | (^ y ")' . "y" może pojawić się na początku łańcucha, a ten przypadek nie jest objęty '/ [^ x] y /'. – approxiblue

Odpowiedz

34

Potrzebujesz negatywnej opinii o zerowej szerokości. Wypróbuj /(?<!x)y/, która mówi dokładnie to, czego szukasz, tj. Znajdź cały "y" nie poprzedzony przez "x", ale nie zawiera poprzedniego znaku, który jest częścią o zerowej szerokości.

Edytowany w celu dodania: Wygląda na to, że jest to obsługiwane tylko w Rubim 1.9 i wyżej.

-1

W PCRE, należy użyć negatywny wygląd opóźnieniem:

(:<!x)y 

nie wiem, czy jest to obsługiwane przez Ruby, ale zawsze możesz spojrzeć w górę.

-1

To można zrobić z negatywną wygląd tyłu, (?<!x)y

2

Ruby niestety nie obsługuje negatywny lookbehind, więc będziesz mieć problemy, jeśli trzeba spojrzeć na więcej niż jednego znaku. Tylko dla jednej postaci, można zadbać o to poprzez przechwytywanie meczu:

/[^x](y)/ 
+0

Ah, nie jestem ekspertem od Ruby - jbourque mówi, że negatywny lookbehind jest w nowszej Ruby. Oto twoja prawdziwa odpowiedź. – Cascabel

+0

[^ x] musi pasować do jednego znaku. jeśli y pojawi się na początku linii, powinniśmy ją dopasować:/(?: \ A |^| [^ x]) y / –

3

Negative look-tył nie jest obsługiwana aż Ruby 1.9, ale można zrobić coś podobnego przy użyciu skanowania:

"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"] 

Oczywiście jest to znacznie trudniejsze, jeśli chcesz uniknąć znacznie więcej niż jednej postaci przed y. Wtedy musielibyśmy zrobić coś w rodzaju:

"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"] 
Powiązane problemy