2009-05-22 7 views
11

Próbuję sparsować ciąg wieloliniowy i uzyskać resztę linii zgodnie ze wzorcem.Co to jest "ruby", aby przeanalizować ciąg znaków dla pojedynczego klucza/wartości?

tekst:

 
hello john 
your username is: jj 
thanks for signing up 

chcę wyodrębnić jj, alias wszystko po "nazwa użytkownika to:"

Jednym ze sposobów:

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

Ale to przypomina mi Perl .. i nie "czyta" tak naturalnie, jak mi mówiono, że ruby ​​powinien.

Czy istnieje czystszy sposób? AKA Sposób "rubinowy"?

Dzięki

+1

Rubin był dość mocno inspirowany przez Perla; miał on pasować do tej samej niszy, co Perl, ale z ładnym systemem obiektów i składnią, która była czystsza i bardziej regularna. W rzeczywistości ma wiele funkcji pobranych wprost z Perla, jak ruby ​​-p -i -e, chociaż niektóre z bardziej podobnych funkcji w Perlu są teraz przestarzałe. –

Odpowiedz

22

Twój kod jest całkiem dużo Ruby sposób. Jeśli nie chcesz korzystać z globalnej $1, można użyć wersji 2 arg String#[]:

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

Dzięki. Właśnie tego szukałem! Wyciąganie globalnych dolarów wydawało się zbyt stare. Poszedłem i przeczytałem dokumenty API dla Ruby, Class: String i tam to było. http://www.ruby-doc.org/core/classes/String.html#M000786 – SWR

6

podzielona komenda jest mindbogglingly użyteczne. Dzieli ciąg znaków na tablicę podłańcuchów, oddzielając się od tego, co przekazujesz. Jeśli nie podasz żadnych argumentów, dzieli się na białe znaki. Jeśli więc znasz słowo, którego szukasz, to piąte "słowo" (dzielenie na obie spacje i znak powrotu), możesz to zrobić:

text = "hello john \ nhz nazwa użytkownika to: jj \ nDziękujemy na podpisanie \ n”
match = text.split [5]

..ale chyba że nie jest wystarczająco samodokumentujące, czy chcesz zezwolić na mecze multi-word. Można to zrobić w zamian:

środkowej = text.split ("\ n") [1]
match = midline.split ("nazwa użytkownika to:") .last

czy może tym bardziej zwięzły sposób:

match = tekst [/ nazwa użytkownika to: (. *)/1]

+0

Zrobiłbym to, ale podzielono na "" zamiast "Twoja nazwa użytkownika to:" –

+1

+1 za ciekawe wykorzystanie podziału, aby uzyskać piąte słowo, nie zauważyłem tego. –

+2

Wow, dzięki za wiele ścieżek ataku.;) Nie zauważyłem możliwości podziału, ale przychodzący tekst nie jest statyczny (przykład został znacznie uproszczony), więc nie zadziała ... ale był to dobry sposób na zaatakowanie problemu. – SWR

4

Nie jestem pewien, czy jest to bardziej Ruby'ish, ale inna opcja:

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

Tak to zrobię. To nie jest technicznie lepsze od rozwiązania [], ale myślę, że zamiar jest wyraźniejszy, kiedy go przeglądasz. – Chuck

3

Jest również Regexp#match, który zwraca obiekt MatchData, który ma wszystkie informacje, które możesz chcieć.

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"