Necesita el método Regexp#match
. Si escribe /\[(.*?)\](.*)/.match('[ruby] regex')
, esto devolverá un objeto MatchData
. Si llamamos a ese objeto matches
, entonces, entre otras cosas:
matches[0]
devuelve toda la cadena coincidente.
matches[n]
devuelve el enésimo grupo de captura ($n
).
matches.to_a
devuelve una matriz que consiste en matches[0]
hasta matches[N]
.
matches.captures
devuelve una matriz que consiste en solo el grupo de captura (matches[1]
a matches[N]
).
matches.pre_match
devuelve todo antes de la cadena coincidente.
matches.post_match
devuelve todo después de la cadena coincidente.
Existen más métodos, que corresponden a otras variables especiales, etc .; Puede marcar MatchData
's docs para más. Por lo tanto, en este caso específico, todo lo que necesita para escribir es
tag, keyword = /\[(.*?)\](.*)/.match('[ruby] regex').captures
Edición 1: bien, para su tarea más difícil, usted va a querer en lugar del método String#scan
, que @Theo utilizado; sin embargo, vamos a usar una expresión regular diferente. El siguiente código debería funcionar:
# You could inline the regex, but comments would probably be nice.
tag_and_text =/\[([^\]]*)\] # Match a bracket-delimited tag,
\s* # ignore spaces,
([^\[]*) /x # and match non-tag search text.
input = '[ruby] [regex] [rails] one line [foo] [bar] baz'
tags, texts = input.scan(tag_and_text).transpose
la input.scan(tag_and_text)
devolverá una lista de pares de marcado y búsqueda de texto:
[ ["ruby", ""], ["regex", ""], ["rails", "one line "]
, ["foo", ""], ["bar", "baz"] ]
La llamada transpose
voltea que, para que tenga un par que consiste en una etiqueta lista y una lista de texto de búsqueda:
[["ruby", "regex", "rails", "foo", "bar"], ["", "", "one line ", "", "baz"]]
A continuación, puede hacer lo que quiera con los resultados. Que podría sugerir, por ejemplo
search_str = texts.join(' ').strip.gsub(/\s+/, ' ')
Esto concatenar los fragmentos de búsqueda con espacios individuales, deshacerse de espacio inicial y final, y vuelva a colocar carreras de espacios múltiples con un solo espacio.
Para la actualización: si quisiera hacer esto en una sola expresión regular, necesitaría el motor de expresiones regulares .NET o Perl 6, actualmente los únicos que admiten capturas dentro de elementos repetidos. Entonces, con IronRuby, probablemente tendrías una oportunidad. Ver también http://stackoverflow.com/questions/2652554/which-regex-flavors-support-captures-as-opposed-to-capturing-groups - sin embargo, para la legibilidad y la mantenibilidad, un enfoque de dos pasos es probablemente más sensato . –