Ruby'deki bir dizeden normal bir ifade kullanarak bir alt dizeyi çıkarın


130

Ruby'de bir dizenin içinden bir alt dizeyi nasıl çıkarabilirim?

Misal:

String1 = "<name> <substring>"

Ben ayıklamak istiyorum substringden String1(son oluş içinde yani her şey <ve >).

Yanıtlar:


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

scanher biri için, bir dizi oluşturur <item>in String1arasında metin içeren <ve >(bir normal ifade yakalama gruplarını ihtiva eden birlikte kullanıldığında, tarama her bir maç için yakalar ihtiva eden bir dizi oluşturur, çünkü) tek eleman dizideki. lastsize bu dizilerin sonunu firstverir ve sonra size içindeki dizeyi verir.


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

scanTek bir sonuca ihtiyacımız varsa kullanmaya gerek yok .
Ruby'lerimiz matchvarken Python'u kullanmaya gerek yok String[regexp,#].

Bakınız: http://ruby-doc.org/core/String.html#method-i-5B-5D

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


37
Diğer tamamen geçerli (ve daha okunabilir) çözümlerin itibarını düşürmeye gerek yok.
coreyward

41
@coreyward, eğer daha iyilerse, lütfen tartış. Örneğin, sepp2k'in çözümü daha esnektir ve bu yüzden çözümüme işaret if we need only one resultettim. Ve match()[]daha yavaştır çünkü bu bir yerine iki yöntemdir.
Nakilon

4
Bu, sunulan tüm yöntemlerin en hızlısıdır, ancak en yavaş yöntem bile makinemde yalnızca 4,5 mikrosaniye sürmektedir. Bu yöntemin neden daha hızlı olduğunu tahmin etmeyi umursamıyorum. Performansta spekülasyon işe yaramaz . Yalnızca ölçüm önemlidir.
Wayne Conrad

8
Bu çözümü daha basit ve isabetli buluyorum (Ruby'de yeni olduğum için). Teşekkürler.
Ryan H.

@Nakilon Okunabilirlik, bir ürünün ve ekibin genel başarısı düşünüldüğünde küçük performans farklılıklarından daha ağır basabilir, bu yüzden coreyward geçerli bir yorum yaptı. Bununla birlikte, string[regex]bu senaryoda da aynı derecede okunabilir olduğunu düşünüyorum , bu yüzden kişisel olarak kullandım.
Nick

24

Bunun için normal bir ifadeyi oldukça kolay bir şekilde kullanabilirsiniz ...

Kelimenin etrafında boşluklara izin vermek (ancak onları tutmamak):

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

Veya izin verilen boşluklar olmadan:

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

1
<>Sonuncunun dizedeki son şey olması gerektiğinden emin değilim . Örneğin dizeye foo <bar> bazizin veriliyorsa (ve sonucu vermesi gerekiyorsa bar), bu çalışmayacaktır.
sepp2k

Sağladığı örnek diziye göre gittim.
coreyward

10

matchYöntemi kullanarak biraz daha esnek bir yaklaşım burada . Bununla, birden fazla dizeyi ayıklayabilirsiniz:

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

Daha basit bir tarama şöyle olacaktır:

String1.scan(/<(\S+)>/).last
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.