Interpolando uma Cadeia de Caracteres em uma Regex

160

Preciso substituir o valor de uma string na minha expressão regular em Ruby. Existe uma maneira fácil de fazer isso? Por exemplo:

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
fonte
Você está tentando ver se foo é uma substring de goo? Não acho claro o que você está perguntando.
Neall 29/09/08
Se sim, goo.include? (Foo) é suficiente!
Glenn McDonald
1
Não, eu não estava tentando ver se foo é uma substring de goo; Eu também precisava fazer algumas capturas, portanto, incluir não funcionou.
Chris Bunch

Respostas:

274

O mesmo que inserção de string.

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

Note que o Regexp.quoteem resposta de Jon L. é importante!

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

Se você acabou de fazer a versão "óbvia":

if goo =~ /#{foo}/

os períodos no texto da correspondência serão tratados como curingas de expressão regular e "0.0.0.0"corresponderão "0a0b0c0".

Observe também que, se você realmente deseja apenas verificar uma correspondência de substring, pode simplesmente fazer

if goo.include?(foo)

que não requer uma citação adicional ou se preocupa com caracteres especiais.

glenn mcdonald
fonte
3
Observe que o inverso (sem usar .quote()) também pode ser útil se você estiver procurando construir uma regex usando uma string.
Jesse
"se você realmente quer apenas verificar se há uma correspondência de substring, pode simplesmente if goo.include?(foo)" => True quando estiver interessado em verificar a existência. Se você estiver interessado em substituir e já usar o String.gsub, o Regexp.quote pode ser sua única opção.
Isaac Betesh
Só para acrescentar sobre a Jesse no caso não é óbvio, isso significa apenas passando a cadeia de caracteres que você não precisa escaparam ao Regexp.newou Regexp.compile.
dylankb
Obrigado pela explicação útil de por que podemos usar o Regexp.quote #
Wylliam Judd 22/10/1918
7

Provavelmente Regexp.escape(foo)seria um ponto de partida, mas há uma boa razão para você não usar a interpolação de expressão mais convencional "my stuff #{mysubstitutionvariable}":?

Além disso, você pode apenas usar !goo.match(foo).nil?com uma string literal.

JasonTrue
fonte
6
Regexp.compile(Regexp.escape(foo))
Markus Jarderot
fonte
3

Use Regexp.new:

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

Aqui está uma outra resposta limitada, mas útil:

Eu descobri que posso inserir facilmente em uma regex sem usar Regexp.quote ou Regexp.escape se eu apenas use aspas simples na minha string de entrada: (uma correspondência de endereço 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"

aspas simples interpretam apenas \\ e \ '.

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

Isso me ajudou quando eu precisei usar a mesma parte longa de um regex várias vezes. Não é universal, mas se encaixa no exemplo da pergunta, acredito.

Plasmarob
fonte
Estou curioso para saber o que será pensado no meu post aqui, mas duvido que seja visto tão longe aqui agora.
Plasmarob
-2
foo = "0.0.0.0"
goo = "here is some other stuff 0.0.0.0" 

puts "success!" if goo =~ /#{foo}/
Mike Breen
fonte
2
Não, isso dará um erro "true" para "aqui estão outras coisas 070x0! 0", porque os pontos são caracteres curinga de regexp.
Glenn McDonald