Existe uma maneira rápida de encontrar todas as correspondências de uma expressão regular no Ruby? Eu olhei através do objeto Regex no Ruby STL e procurei no Google sem sucesso.
Mas o que é esse caso? "combine comigo!". scan (/.../) = ["mat", "ch" "eu!" ], mas todas as ocorrências de /.../ seriam ["mat", "atc", "tch", "ch", ...]
Michael Dickens
13
Não, não seria. /.../ é um regexp ganancioso normal. Não retornará ao conteúdo correspondente. você pode tentar usar um regexp lento, mas mesmo isso provavelmente não será suficiente. ter um olhar para o doc regexp ruby-doc.org/core-1.9.3/Regexp.html para expressar correctamente o seu regexp :)
Jean
49
isso parece um WTF Ruby ... por que isso está em String em vez de Regexp com as outras coisas de regexp? Nem sequer é mencionado em qualquer lugar sobre os docs para Regexp
Anentropic
9
Eu acho que é porque é definido e chamado String, não no Regex ... Mas, na verdade, faz sentido. Você pode escrever uma expressão regular para capturar todas as correspondências usando Regex # match e iterar sobre os grupos capturados. Aqui, você escreve uma função de correspondência parcial e deseja que ela seja aplicada várias vezes em uma determinada sequência, isso não é responsabilidade do Regexp. Eu sugiro que você verificar a aplicação de digitalização para obter uma melhor compreensão: ruby-doc.org/core-1.9.3/String.html#method-i-scan
Jean
9
@ MichaelDickens: Nesse caso, você pode usar /(?=(...))/.
Konrad Borowski
67
Para encontrar todas as seqüências correspondentes, use o scanmétodo String .
str.scan(/\d+[m-t]/) # => ["54m", "1t", "3r"]é mais idiomático do questr.to_enum(:scan,re).map {$&}
o Homem de Lata
Talvez você tenha entendido errado. A expressão regular do exemplo de um usuário que eu respondi foi: /(\d+)[m-t]/não /\d+[m-t]/Escrever: re = /(\d+)[m-t]/; str.scan(re)é o mesmo, str.scan(/(\d+)[mt]/)mas recebo #> [["" 54 "], [" 1 "], [" 3 "]]e não "54m", "1t", "3r"]A pergunta era: se eu tenho uma expressão regular com um grupo e quero capturar todos os padrões sem alterar o padrão expressão (saindo do grupo), como posso fazer isso? Nesse sentido, uma solução possível, embora um pouco enigmática e difícil de ler, foi:str.to_enum(:scan,re).map {$&}
MVP
-1
Você pode usar string.scan(your_regex).flatten. Se o seu regex contiver grupos, ele retornará em uma única matriz simples.
Remova o agrupamento de your_regex = /(\d+)[m-t]/e você não precisará usá-lo flatten. Seu exemplo final usa last_matchque, nesse caso, provavelmente é seguro, mas é global e pode ser substituído se qualquer expressão regular corresponder antes da chamada last_match. Em vez disso, é provavelmente mais seguro de usar string.match(regex).captures # => ["group_photo", "jpg"]ou string.scan(/\d+/) # => ["54", "3", "1", "7", "3", "0"]como mostrado em outras respostas, dependendo do padrão e das necessidades.
Respostas:
Usar
scan
deve fazer o truque:fonte
/(?=(...))/
.Para encontrar todas as seqüências correspondentes, use o
scan
método String .Se você quiser,
MatchData
que é o tipo do objeto retornado pelomatch
método Regexp , use:A vantagem de usar
MatchData
é que você pode usar métodos comooffset
:Veja estas perguntas se quiser saber mais:
Lendo sobre variáveis especiais
$&
,$'
,$1
,$2
em Ruby será útil também.fonte
se você tiver uma regexp com grupos:
você pode usar o
scan
método String para encontrar grupos correspondentes:Para encontrar o padrão correspondente:
fonte
str.scan(/\d+[m-t]/) # => ["54m", "1t", "3r"]
é mais idiomático do questr.to_enum(:scan,re).map {$&}
/(\d+)[m-t]/
não/\d+[m-t]/
Escrever:re = /(\d+)[m-t]/; str.scan(re)
é o mesmo,str.scan(/(\d+)[mt]/)
mas recebo #>[["" 54 "], [" 1 "], [" 3 "]]
e não"54m", "1t", "3r"]
A pergunta era: se eu tenho uma expressão regular com um grupo e quero capturar todos os padrões sem alterar o padrão expressão (saindo do grupo), como posso fazer isso? Nesse sentido, uma solução possível, embora um pouco enigmática e difícil de ler, foi:str.to_enum(:scan,re).map {$&}
Você pode usar
string.scan(your_regex).flatten
. Se o seu regex contiver grupos, ele retornará em uma única matriz simples.Regex também pode ser um grupo nomeado.
Você também pode usar
gsub
, é apenas mais uma maneira se você quiser o MatchData.fonte
your_regex = /(\d+)[m-t]/
e você não precisará usá-loflatten
. Seu exemplo final usalast_match
que, nesse caso, provavelmente é seguro, mas é global e pode ser substituído se qualquer expressão regular corresponder antes da chamadalast_match
. Em vez disso, é provavelmente mais seguro de usarstring.match(regex).captures # => ["group_photo", "jpg"]
oustring.scan(/\d+/) # => ["54", "3", "1", "7", "3", "0"]
como mostrado em outras respostas, dependendo do padrão e das necessidades.