2010-01-06 4 views
7

Bir dizeyi Ruby'deki bir parça listesine ayırmam gerekiyor, ancak parantez içinde bulunan öğeleri göz ardı etmem gerekiyor. Örneğin:Parantez içeriklerini göz ardı ederek Ruby'de dize ayırın mı?

[0]A +4 
[1]B +6 
[2]C (hello, goodbye) +5 
[3]D +3 

Ama bu parantez içeriğini bölmek çünkü ben sadece, virgül üzerinde bölemezsiniz:

A +4, B +6, C (hello, goodbye) +5, D +3 

ben olmak çıkan listesi istiyorsunuz. Parantez içindeki virgülleri başka bir şeye ayırmadan parçaları dağıtmanın bir yolu var mı?

Teşekkürler.

+0

ayrıştırma karıştırmasını :-(frowny yüzleri dikkat –

cevap

13

bu deneyin:

s = 'A +4, B +6, C (hello, goodbye) +5, D +3' 
tokens = s.scan(/(?:\(.*?\)|[^,])+/) 
tokens.each {|t| puts t.strip} 

Çıktı:

A +4 
B +6 
C (hello, goodbye) +5 
D +3 

Kısa açıklama: Başka bir seçenek, bazı alanlarda ardından virgül üzerinde bölmek olduğunu

(?:  # open non-capturing group 1 
    \(  # match '(' 
    .*?  # reluctatly match zero or more character other than line breaks 
    \)  # match ')' 
    |  # OR 
    [^,]  # match something other than a comma 
)+   # close non-capturing group 1 and repeat it one or more times 

yalnızca ilk İleriye bakıldığında görülebilen parantez, bir açılış parantezidir (ya da hiç parantez yoktur). dize sonu):

s = 'A +4, B +6, C (hello, goodbye) +5, D +3' 
tokens = s.split(/,\s*(?=[^()]*(?:\(|$))/) 
tokens.each {|t| puts t} 

aynı çıktıyı üretecek ama scan yöntem temizleyici bulabilirsiniz.

+0

# => [ "Bir 4", "B 6", "C (! merhaba, hoşçakal) +5 "," D +3 "] Benim için mükemmel görünüyor.Yağlıklı boşlukları kaldırmak için onu kırpmak isteyebilirsin.T –

+0

:) zaten boşlukları gördü ve 'trim'i eklendi –

+0

Harika cevap, teşekkürler:) – Colen

5
string = "A +4, B +6, C (hello, goodbye) +5, D +3" 
string.split(/ *, *(?=[^\)]*?(?:\(|$))/) 
# => ["A +4", "B +6", "C (hello, goodbye) +5", "D +3"] 

Bu nasıl regex çalışır:

/ 
    *, *  # find comma, ignoring leading and trailing spaces. 
    (?=   # (Pattern in here is matched against but is not returned as part of the match.) 
    [^\)]*? # optionally, find a sequence of zero or more characters that are not ')' 
    (?:  # <non-capturing parentheses group> 
     \(  #  left paren ')' 
     |  #  - OR - 
     $  #  (end of string) 
    ) 
) 
/
+0

Bu OP muhtemelen muhtemelen yüreksiz regex meraklısı için bir açıklama olmadan biraz şifreli olabilir! :). Ama yine de iyi bir çözüm. –

+0

Bu nasıl çalışır? Ben regex bölünmüş ile çalıştı nasıl iyi bir belge bulamadım Bart K. reheksik – Colen

+0

@ Colen ile bu kadar büyük değilim, ben bir açıklama dahil ikinci bir çözüm olarak çok benzer bir regex yayınladı. –