2009-05-22 6 views
11

J'essaye d'analyser une chaîne multi-lignes et obtenir le reste de la ligne suivant un modèle.Quelle est la "méthode ruby" pour analyser une chaîne pour une seule clé/valeur?

texte:

 
hello john 
your username is: jj 
thanks for signing up 

Je veux extraire J.-J., alias tout ce qui suit "votre nom d'utilisateur est:"

Une façon:

text = "hello john\nyour username is: jj\nthanks for signing up\n" 
match = text[/your username is: (.*)/] 
value = $1 

Mais cela me rappelle perl .. et ne "lit" pas aussi naturellement qu'on le dit à Ruby.

Y a-t-il une manière plus propre? AKA Une façon "rubis"?

Merci

+1

Ruby était en fait assez fortement inspiré par Perl; il était censé rentrer dans la même niche que Perl, mais avec un bon système d'objets et une syntaxe plus propre et plus régulière. Il a en fait un certain nombre de caractéristiques tirées directement de Perl, comme ruby ​​-p -i -e, bien que certaines des fonctionnalités similaires à Perl soient désormais obsolètes. –

Répondre

22

Votre code est à peu près la façon dont Ruby. Si vous ne voulez pas utiliser le $1 global, vous pouvez utiliser le 2 arg Version String#[]:

match = text[/your username is: (.*)/, 1] 
+0

Merci. C'est exactement ce que je cherchais! Tirer vers le haut des globals de dollar a juste semblé l'école trop vieille. Je suis allé lire les documents de l'API pour Ruby, Class: String et voilà. http://www.ruby-doc.org/core/classes/String.html#M000786 – SWR

6

La commande est divisé mindbogglingly utile. Il divise une chaîne en un tableau de sous-chaînes, en se séparant sur tout ce que vous passez. Si vous ne lui donnez aucun argument, il se sépare en espaces. Donc, si vous connaissez le mot que vous cherchez est le cinquième « mot » (séparation des deux espaces et le caractère de retour), vous pouvez le faire:

text = « Bonjour John \ nvotre nom d'utilisateur est: J.-J. \ nMerci pour la signature \ n »
match = text.split [5]

..mais peut-être ce n'est pas suffisamment autodocumenté, ou que vous souhaitez autoriser des correspondances à plusieurs mots. Vous pouvez le faire à la place:

= text.split ligne médiane ("\ n") [1]
match = midline.split ("nom d'utilisateur est:") .last

Ou peut-être cette plus laconique façon:

match = texte [/ nom d'utilisateur est: (. *) /, 1]

+0

je le ferais, mais diviser sur "" au lieu de "votre nom d'utilisateur est:" –

+1

+1 pour une utilisation intéressante de split pour obtenir le cinquième mot, je n'avais pas remarqué cela. –

+2

Wow, merci pour les multiples chemins d'attaque.;) Je n'avais pas remarqué la possibilité de split, mais le texte entrant n'est pas statique (l'exemple a été grandement simplifié) donc ça ne marchera pas ... mais c'était une bonne façon d'attaquer le problème. – SWR

4

Je ne sais pas si elle est plus Ruby'ish, mais une autre option:

>> text = "hello john\nyour username is: jj\nthanks for signing up\n" 
>> text.match(/your username is: (.*)/)[1] 
=> "jj" 
+2

Voici comment je le ferais. Ce n'est pas techniquement supérieur à la solution [], mais je pense que l'intention est plus claire quand on l'écrase. – Chuck

3

Il y a aussi Regexp#match, ce qui renvoie un objet MatchData, qui contient toutes les informations que vous pourriez vouloir.

irb> match = /your username is: (.*)/.match "hello john\nyour username is: jj\nthanks for signing up\n" 
#=> #<MatchData:0x557f94> 
irb> match.pre_match 
#=> "hello john\n" 
irb> match.post_match 
#=> "\nthanks for signing up\n" 
irb> match[0] 
#=> "your username is: jj" 
irb> match[1] 
#=> "jj"