Interpolacja ciągu znaków do wyrażenia regularnego


160

Muszę podstawić wartość ciągu w moim wyrażeniu regularnym w Rubim. Czy jest na to łatwy sposób? Na przykład:

foo = "0.0.0.0"
goo = "here is some other stuff 0.0.0.0" 
if goo =~ /value of foo here dynamically/
  puts "success!"
end

Czy próbujesz sprawdzić, czy foo jest podciągiem mazi? Myślę, że nie jest jasne, o co pytasz.
Neall

Jeśli tak, wystarczy goo.include? (Foo)!
glenn mcdonald

1
Nie, nie próbowałem sprawdzić, czy foo jest podciągiem mazi; Musiałem też zrobić trochę przechwytywania, więc dołączanie nie działało.
Chris Bunch,

Odpowiedzi:



125

Zauważ, że Regexp.quotew Jon L. za odpowiedź jest ważna!

if goo =~ /#{Regexp.quote(foo)}/

Jeśli wybierzesz tylko „oczywistą” wersję:

if goo =~ /#{foo}/

wtedy kropki w tekście dopasowania są traktowane jako symbole wieloznaczne wyrażenia regularnego i "0.0.0.0"będą zgodne "0a0b0c0".

Zauważ również, że jeśli naprawdę chcesz tylko sprawdzić dopasowanie podłańcucha, możesz po prostu to zrobić

if goo.include?(foo)

który nie wymaga dodatkowego cytowania ani martwienia się o znaki specjalne.


3
Zwróć uwagę, że odwrotność (nieużywanie .quote()) może być również przydatna, jeśli chcesz skonstruować wyrażenie regularne za pomocą ciągu.
Jesse

"jeśli naprawdę chcesz tylko sprawdzić dopasowanie podłańcucha, możesz po prostu zrobić if goo.include?(foo)" => True, gdy chcesz sprawdzić istnienie. Jeśli jesteś zainteresowany zastąpieniem i już korzystaniem z String.gsub, wówczas Regexp.quote może być jedyną opcją.
Isaac Betesh,

Aby dodać do Jesse na wypadek, gdyby nie było to oczywiste, oznacza to po prostu przekazanie ciągu znaków, do których nie potrzebujesz ucieczki Regexp.newlub Regexp.compile.
dylankb

Dziękuję za przydatne wyjaśnienie, dlaczego możemy chcieć skorzystać z Regexp. Cytat
Wylliam Judd

7

Prawdopodobnie Regexp.escape(foo)będzie to punkt wyjścia, ale jest to dobry powód, dla którego nie mogą korzystać z bardziej konwencjonalną ekspresję interpolacji: "my stuff #{mysubstitutionvariable}"?

Możesz też po prostu użyć !goo.match(foo).nil?z literałem.




3

Oto ograniczona, ale użyteczna inna odpowiedź:

Odkryłem, że mogę łatwo wstawić do wyrażenia regularnego bez użycia Regexp.quote lub Regexp.escape, jeśli użyłem tylko apostrofów w moim ciągu wejściowym: (pasujący adres IP)

IP_REGEX = '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'

my_str = "192.0.89.234 blahblah text 1.2, 1.4" # get the first ssh key 
# replace the ip, for demonstration
my_str.gsub!(/#{IP_REGEX}/,"192.0.2.0") 
puts my_str # "192.0.2.0 blahblah text 1.2, 1.4"

pojedyncze cudzysłowy interpretują tylko znaki \\ i \ '.

http://en.wikibooks.org/wiki/Ruby_Programming/Strings#Single_quotes

Pomogło mi to, gdy musiałem kilkakrotnie użyć tej samej długiej części wyrażenia regularnego. Nie uniwersalne, ale moim zdaniem pasuje do przykładu pytania.


jestem ciekawy, co będzie pomyślane o moim wpisie tutaj, ale wątpię, że będzie to teraz widoczne tak daleko tutaj.
Plasmarob

-2
foo = "0.0.0.0"
goo = "here is some other stuff 0.0.0.0" 

puts "success!" if goo =~ /#{foo}/

2
Nie, to da błędne „prawda” dla „tutaj jest kilka innych rzeczy 070x0! 0”, ponieważ kropki są symbolami wieloznacznymi wyrażeń regularnych.
glenn mcdonald
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.