Извлечь подстроку из строки в Ruby с помощью регулярного выражения

131

Как я могу извлечь подстроку из строки в Ruby?

Пример:

String1 = "<name> <substring>"

Я хочу извлечь substringиз String1(т. Е. Все, что было до последнего появления <и >).

Madhusudhan
источник

Ответы:

134
String1.scan(/<([^>]*)>/).last.first

scanсоздает массив, который для каждого <item>in String1содержит текст между <и >в одноэлементном массиве (потому что при использовании с регулярным выражением, содержащим группы захвата, сканирование создает массив, содержащий захваты для каждого совпадения). lastдает вам последний из этих массивов, а firstзатем дает вам строку в нем.

sepp2k
источник
321
"<name> <substring>"[/.*<([^>]*)/,1]
=> "substring"

Не нужно использовать scan, если нужен только один результат.
Нет необходимости использовать Python match, когда у нас есть Ruby String[regexp,#].

См. Http://ruby-doc.org/core/String.html#method-i-5B-5D.

Примечание: str[regexp, capture] → new_str or nil

Nakilon
источник
37
Нет нужды дискредитировать другие совершенно корректные (и, могу ли я предположить, более читаемые) решения.
Coreyward 06
41
@coreyward, если они лучше, пожалуйста, аргументируйте. Например, решение sepp2k более гибкое, и поэтому я указал if we need only one resultна свое решение. И match()[]медленнее, потому что это два метода вместо одного.
Nakilon
4
Это самый быстрый из всех представленных методов, но даже самый медленный метод занимает на моей машине всего 4,5 микросекунды. Я не хочу строить догадки, почему этот метод быстрее. По производительности домыслы бесполезны . Важны только измерения.
Уэйн Конрад,
8
Я считаю это решение более простым и точным (поскольку я новичок в Ruby). Спасибо.
Райан Х.
@Nakilon Readability может перевесить крошечные различия в производительности при рассмотрении общего успеха продукта и команды, поэтому Coreyward сделал правильный комментарий. Тем не менее, я думаю, string[regex]что в этом сценарии он может быть таким же читаемым, поэтому я лично использовал его.
Ник
24

Вы можете легко использовать регулярное выражение для этого ...

Допускаем пробелы вокруг слова (но не оставляем их):

str.match(/< ?([^>]+) ?>\Z/)[1]

Или без разрешенных пробелов:

str.match(/<([^>]+)>\Z/)[1]
coreyward
источник
1
Я не уверен, что последнее <>действительно должно быть последним в строке. Если, например, строка foo <bar> bazразрешена (и должна давать результат bar), это не сработает.
sepp2k 06
Я просто руководствовался предоставленной им образцовой строкой.
Coreyward 06
10

Вот несколько более гибкий подход с использованием этого matchметода. С его помощью вы можете извлечь более одной строки:

s = "<ants> <pants>"
matchdata = s.match(/<([^>]*)> <([^>]*)>/)

# Use 'captures' to get an array of the captures
matchdata.captures   # ["ants","pants"]

# Or use raw indices
matchdata[0]   # whole regex match: "<ants> <pants>"
matchdata[1]   # first capture: "ants"
matchdata[2]   # second capture: "pants"
Грант Бирчмайер
источник
3

Более простое сканирование:

String1.scan(/<(\S+)>/).last
Навид
источник