2010-01-05 9 views
10

¿Hay alguna manera de crear la expresión regular /func:\[sync\] displayPTS/ a partir de la cadena func:[sync] displayPTS?Crear expresión regular de la cadena

La historia detrás de esta pregunta es que tengo patrones de cadena serval para buscar en un archivo de texto y no quiero escribir lo mismo una y otra vez.

File.open($f).readlines.reject {|l| not l =~ /"#{string1}"/} 
File.open($f).readlines.reject {|l| not l =~ /"#{string2}"/} 

En su lugar, yo quiero tener una función para hacer el trabajo:

def filter string 
      #build the reg pattern from string 
      File.open($f).readlines.reject {|l| not l =~ pattern} 
    end 
    filter string1 
    filter string2 
+0

En lugar de convertir la cadena de una expresión regular, ¿no hay una función de búsqueda que * no * tome una expresión regular como parámetro? – mpen

+0

@Mark, muy buen punto! – pierrotlefou

Respuesta

20
s = "func:[sync] displayPTS" 
# => "func:[sync] displayPTS" 
r = Regexp.new(s) 
# => /func:[sync] displayPTS/ 
r = Regexp.new(Regexp.escape(s)) 
# => /func:\[sync\]\ displayPTS/ 
0

Cómo sobre el uso %r{}:

my_regex = "func:[sync] displayPTS" 
File.open($f).readlines.reject { |l| not l =~ %r{#{my_regex}} } 
+0

Eso no escapará a los corchetes. –

3

Si las cadenas son sólo cadenas, se puede combinarlos en una expresión regular, así:

targets = [ 
    "string1", 
    "string2", 
].collect do |s| 
    Regexp.escape(s) 
end.join('|') 
targets = Regexp.new(targets) 

Y luego:

lines = File.readlines('/tmp/bar').reject do |line| 
    line !~ target 
end 

s !~ regexp es equivalente a not s =~ regexp, pero más fácil de leer.

Evita usar File.open sin cerrar el archivo. El archivo permanecerá abierto hasta que el objeto del archivo descartado sea basura, lo que podría ser lo suficientemente largo como para que su programa se quede sin controladores de archivos. Si usted tiene que hacer algo más que leer las líneas, entonces:

File.open(path) do |file| 
    # do stuff with file 
end 

Rubí cerrará el archivo al final del bloque.

También podría considerar si usar find_all y una coincidencia positiva sería más fácil de leer que rechazar y una coincidencia negativa. El menor número de negativos mente del lector tiene que pasar, más clara será la de código:

lines = File.readlines('/tmp/bar').find_all do |line| 
    line =~ target 
end 
+0

+1 para la forma de bloque de 'File.open' y' find_all' – pierrotlefou

10

me gusta la respuesta de Bob, pero sólo para ahorrar el tiempo de su teclado:

string = 'func:\[sync] displayPTS' 
/#{string}/ 
+0

Su solución no funcionará porque no escapa a los corchetes que rodean a 'sync', mientras que la solución de Bob sí. –

+0

Creo que la pregunta era más sobre cómo hacer expresiones regulares interpoladas, pero punto justo. actualizado – trevorgrayson

Cuestiones relacionadas