Interpolasi string ke dalam regex

160

Saya perlu mengganti nilai string ke dalam ekspresi reguler saya di Ruby. Apakah ada cara mudah untuk melakukan ini? Sebagai contoh:

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
Chris Bunch
sumber
Apakah Anda mencoba untuk melihat apakah foo adalah substring dari goo? Saya pikir tidak jelas apa yang Anda minta.
Neall
Jika demikian, goo.include? (Foo) sudah cukup!
glenn mcdonald
1
Tidak, saya tidak mencoba melihat apakah foo adalah substring dari goo; Saya juga perlu melakukan beberapa penangkapan, karena itu termasuk tidak bekerja.
Chris Bunch

Jawaban:

274

Sama seperti penyisipan string.

if goo =~ /#{Regexp.quote(foo)}/
#...
Jonathan Lonowski
sumber
125

Perhatikan bahwa Regexp.quotedalam jawaban Jon L. ini penting!

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

Jika Anda hanya melakukan versi "jelas":

if goo =~ /#{foo}/

maka periode dalam teks pertandingan Anda diperlakukan sebagai wildcard regexp, dan "0.0.0.0"akan cocok "0a0b0c0".

Perhatikan juga bahwa jika Anda benar-benar hanya ingin memeriksa kecocokan substring, Anda bisa melakukannya

if goo.include?(foo)

yang tidak memerlukan kutipan tambahan atau mengkhawatirkan karakter khusus.

glenn mcdonald
sumber
3
Perhatikan bahwa kebalikannya (tidak menggunakan .quote()) juga bisa berguna jika Anda ingin membuat regex menggunakan string.
Jesse
"jika Anda benar-benar hanya ingin memeriksa kecocokan substring, Anda dapat melakukan if goo.include?(foo)" => Benar ketika Anda tertarik untuk memeriksa keberadaan. Jika Anda tertarik untuk mengganti dan sudah menggunakan String.gsub, maka Regexp.quote mungkin satu-satunya pilihan Anda.
Isaac Betesh
Hanya untuk menambahkan ke Jesse jika itu tidak jelas, ini berarti hanya melewati serangkaian karakter yang tidak perlu Anda hindari Regexp.newatau Regexp.compile.
dylankb
Terima kasih atas penjelasan yang bermanfaat tentang mengapa kami mungkin ingin menggunakan Regexp.quote
Wylliam Judd
7

Mungkin Regexp.escape(foo)akan menjadi titik awal, tetapi ada alasan yang baik Anda tidak dapat menggunakan ekspresi-interpolasi lebih konvensional: "my stuff #{mysubstitutionvariable}"?

Anda juga bisa menggunakan !goo.match(foo).nil?string literal.

Jason True
sumber
6
Regexp.compile(Regexp.escape(foo))
Markus Jarderot
sumber
3

Gunakan Regexp.new baru:

if goo =~ Regexp.new(foo) # Evaluates to /0.0.0.0/
Jeremy Ruten
sumber
3

Inilah jawaban lain yang terbatas tetapi bermanfaat:

Saya menemukan saya bahwa saya dapat dengan mudah memasukkan ke dalam regex tanpa menggunakan Regexp.quote atau Regexp.escape jika saya hanya menggunakan tanda kutip tunggal pada string input saya: (cocok dengan alamat 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"

kutipan tunggal hanya menafsirkan \\ dan \ '.

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

Ini membantu saya ketika saya perlu menggunakan bagian panjang yang sama dari regex beberapa kali. Tidak universal, tapi cocok dengan contoh pertanyaan, saya percaya.

Plasmarob
sumber
Saya ingin tahu apa yang akan dipikirkan posting saya di sini, tetapi saya ragu itu akan terlihat sejauh ini di sini sekarang.
Plasmarob
-2
foo = "0.0.0.0"
goo = "here is some other stuff 0.0.0.0" 

puts "success!" if goo =~ /#{foo}/
Mike Breen
sumber
2
Tidak, ini akan memberikan kesalahan "true" untuk "di sini ada beberapa hal lain 070x0! 0", karena titik-titik tersebut adalah wildcard regexp.
glenn mcdonald