Extrair uma substring de uma string no Ruby usando uma expressão regular

130

Como posso extrair uma substring de dentro de uma string no Ruby?

Exemplo:

String1 = "<name> <substring>"

Eu quero extrair substringde String1(ou seja, tudo dentro da última ocorrência de <e >).

Madhusudhan
fonte

Respostas:

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

scancria uma matriz que, para cada um <item>em String1contém o texto entre o <eo >numa matriz de um elemento (porque, quando usado com uma expressão regular que contém grupos de captura, digitalização cria uma matriz contendo as capturas para cada jogo). lastfornece a última dessas matrizes e, em firstseguida, fornece a string nela.

sepp2k
fonte
319
"<name> <substring>"[/.*<([^>]*)/,1]
=> "substring"

Não há necessidade de usar scan, se precisarmos de apenas um resultado.
Não há necessidade de usar o Python match, quando temos o Ruby String[regexp,#].

Veja: http://ruby-doc.org/core/String.html#method-i-5B-5D

Nota: str[regexp, capture] → new_str or nil

Nakilon
fonte
37
Não há necessidade de desacreditar outras soluções perfeitamente válidas (e posso opinar, mais legíveis).
coreyward
41
@coreyward, se forem melhores, por favor, argumente. Por exemplo, a solução do sepp2k é mais flexível, e é por isso que apontei if we need only one resultna minha solução. E match()[]é mais lento, porque são dois métodos em vez de um.
Nakilon
4
Este é o mais rápido de todos os métodos apresentados, mas mesmo o método mais lento leva apenas 4,5 microssegundos na minha máquina. Não quero especular por que esse método é mais rápido. No desempenho, a especulação é inútil . Somente a medição conta.
Wayne Conrad
8
Acho essa solução mais direta e objetiva (já que sou novo no Ruby). Obrigado.
Ryan H.
A legibilidade do @Nakilon pode superar as pequenas diferenças de desempenho ao considerar o sucesso geral de um produto e equipe, de modo que a Coreyward fez um comentário válido. Dito isso, acho que string[regex]pode ser tão legível nesse cenário, que foi o que eu usei pessoalmente.
Nick
24

Você pode usar uma expressão regular para isso facilmente ...

Permitindo espaços ao redor da palavra (mas não mantendo-os):

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

Ou sem os espaços permitidos:

str.match(/<([^>]+)>\Z/)[1]
coreyward
fonte
1
Não tenho certeza de que o último <>realmente seja a última coisa na string. Se, por exemplo, a string foo <bar> bazfor permitida (e supostamente fornecer o resultado bar), isso não funcionará.
sepp2k
Eu apenas fui baseado na string de amostra que ele forneceu.
coreyward
10

Aqui está uma abordagem um pouco mais flexível usando o matchmétodo Com isso, você pode extrair mais de uma sequência:

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"
Grant Birchmeier
fonte
3

Uma varredura mais simples seria:

String1.scan(/<(\S+)>/).last
Navid
fonte