Вам нужен метод Regexp#match
. Если вы напишите /\[(.*?)\](.*)/.match('[ruby] regex')
, это вернет объект MatchData
. Если мы назовем этот объект matches
, то, между прочим:
matches[0]
возвращает всю совпадающую строку.
matches[n]
возвращает n-ую группу захвата ($n
).
matches.to_a
возвращает массив, состоящий из matches[0]
- matches[N]
.
matches.captures
возвращает массив, состоящий только из группы захвата (от matches[1]
до matches[N]
).
matches.pre_match
возвращает все до соответствующей строки.
matches.post_match
возвращает все после соответствующей строки.
Есть еще методы, которые соответствуют другим специальным переменным и т. Д .; Вы можете проверить MatchData
документы для получения дополнительной информации. Таким образом, в данном конкретном случае все, что вам нужно написать, это
tag, keyword = /\[(.*?)\](.*)/.match('[ruby] regex').captures
Edit 1: Хорошо, для вашей более сложной задачи вы вместо этого захотите использовать метод String#scan
, который @ Theo использовал; однако мы собираемся использовать другое регулярное выражение. Следующий код должен работать:
# 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
input.scan(tag_and_text)
вернет список пар тег-поиск-текст:
[ ["ruby", ""], ["regex", ""], ["rails", "one line "]
, ["foo", ""], ["bar", "baz"] ]
Вызов transpose
переворачивает это, так что у вас есть пара, состоящая из списка тегов и списка поискового текста:
[["ruby", "regex", "rails", "foo", "bar"], ["", "", "one line ", "", "baz"]]
Затем вы можете делать с результатами все, что захотите. Я мог бы предложить, например,
search_str = texts.join(' ').strip.gsub(/\s+/, ' ')
Это объединит фрагменты поиска с одним пробелом, избавит от начальных и конечных пробелов и заменит серии из нескольких пробелов одним пробелом.