Extraire une sous-chaîne d'une chaîne dans Ruby à l'aide d'une expression régulière


130

Comment puis-je extraire une sous-chaîne d'une chaîne dans Ruby?

Exemple:

String1 = "<name> <substring>"

Je veux extraire substringde String1(c'est-à-dire tout ce qui se trouve dans la dernière occurrence de <et >).

Réponses:


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

scancrée un tableau qui, pour chaque <item>in String1contient le texte entre le <et le >dans un tableau à un élément (car lorsqu'il est utilisé avec une expression régulière contenant des groupes de capture, scan crée un tableau contenant les captures pour chaque correspondance). lastvous donne le dernier de ces tableaux et firstvous donne ensuite la chaîne qu'il contient.


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

Pas besoin d'utiliser scan, si nous n'avons besoin que d'un seul résultat.
Pas besoin d'utiliser Python match, quand on a Ruby String[regexp,#].

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

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


37
Inutile de discréditer d'autres solutions parfaitement valables (et pourrais-je dire, plus lisibles).
coreyward

41
@coreyward, s'ils sont meilleurs, veuillez argumenter. Par exemple, la solution de sepp2k est plus flexible, et c'est pourquoi j'ai pointé if we need only one resultma solution. Et match()[]c'est plus lent, car il s'agit de deux méthodes au lieu d'une.
Nakilon

4
C'est la plus rapide de toutes les méthodes présentées, mais même la méthode la plus lente ne prend que 4,5 microsecondes sur ma machine. Je me fiche de spéculer sur les raisons pour lesquelles cette méthode est plus rapide. En performance, la spéculation est inutile . Seule la mesure compte.
Wayne Conrad

8
Je trouve cette solution plus simple et pertinente (puisque je suis nouveau sur Ruby). Merci.
Ryan H.

La lisibilité @Nakilon peut l'emporter sur de minuscules différences de performances lorsque l'on considère le succès global d'un produit et d'une équipe, donc coreyward a fait un commentaire valable. Cela dit, je pense que cela string[regex]peut être tout aussi lisible dans ce scénario, c'est donc ce que j'ai utilisé personnellement.
Nick

24

Vous pouvez utiliser une expression régulière pour cela assez facilement…

Permettre des espaces autour du mot (mais ne pas les garder):

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

Ou sans les espaces autorisés:

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

1
Je ne suis pas sûr que le dernier <>doive être le dernier de la chaîne. Si par exemple la chaîne foo <bar> bazest autorisée (et supposée donner le résultat bar), cela ne fonctionnera pas.
sepp2k

Je suis juste allé basé sur l'exemple de chaîne qu'il a fourni.
coreyward

10

Voici une approche légèrement plus flexible utilisant la matchméthode. Avec cela, vous pouvez extraire plus d'une chaîne:

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

Une analyse plus simple serait:

String1.scan(/<(\S+)>/).last
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.