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.