2012-10-11 13 views
14

To Ruby 1.8.7 ale powinny być takie same jak dla 1.9.xRuby String podzielić z regex

Próbuję podzielić ciąg na przykład:

a = "foo.bar.size.split('.').last" 
# trying to split into ["foo", "bar","split('.')","last"] 

Zasadniczo dzieląc się w polecenia to oznacza, staram się zrobić to z wyrażenia regularnego, ale nie wiem jak, pomysł był użyć regExp

a.split(/[a-z\(\)](\.)[a-z\(\)]/) 

Tutaj próbują wykorzystać grupę (\.), aby go podzielić, ale nie wydaje się to dobrym podejściem.

+1

To nie jest tak proste, jak myślisz. – sawa

+1

@sawa: zamknąłeś pytanie, ponieważ uważasz, że to zbyt trudne? – iconoclast

+0

@iconoclast Nie pamiętam, ale nie z powodu twojego powodu. – sawa

Odpowiedz

23

myślę, że byłoby to zrobić:

a.split(/\.(?=[\w])/) 

Nie wiem, ile wiesz o regex, ale (?=[\w]) jest uprzedzona, że ​​mówi „tylko dopasować kropkę jeśli następny znak jest literą rodzaj charakteru ". Przestawny nie pobierze dopasowanego tekstu. Po prostu "wygląda". Wynik jest dokładnie taki, czego szukasz:

> a.split(/\.(?=[\w])/) 
=> ["foo", "bar", "size", "split('.')", "last"] 
+0

Wow, doskonale i dziękuję za informacje na temat wcześniejszych. Nie, nie wiedziałem o tym i bardzo dobrze się przy tym uczyć wydaje się bardzo przydatne. –

+1

Nie ma za co. Ta strona jest niesamowita: http://www.regular-expressions.info/ –

+1

Spowoduje to podział ciągu znaków '' foo.bar.size.split ('. Bar') .ostatniego "' na '[" foo ", "bar", "size", "split" ("," bar ")", "last"] ". – sawa

2

tutaj nie mam ruby ​​env. Próbowałem z python re.split(). powyżej

In : re.split("(?<!')\.(?!')",a) 
Out: ['foo', 'bar', 'size', "split('.')", 'last'] 

regex ma negatywny uprzedzona I lookbehind, aby upewnić się, tylko „kropka” między pojedyncze cudzysłowy nie będzie działać jako separator.

Oczywiście, dla danego przykładu przez ciebie, wystarczy jeden lookbehind lub wcześniejszy. możesz wybrać właściwą drogę dla swoich wymagań.

+0

Jak być może zauważyłeś, to nie zadziała poprawnie dla '[" foo "," bar "," size "," split "(" o.b ")", "last"] '. – sawa

7

Obawiam się, że wyrażenia regularne nie zajdą Ci daleko. Rozważmy na przykład następujące wyrażenia (które są również ważne Ruby)

"(foo.bar.size.split('.')).last" 
"(foo.bar.size.split '.').last" 
"(foo.bar.size.split '(.) . .(). .').last" 

Problemem jest to, że lista połączeń jest rzeczywiście drzewo połączeń. Najprostszym rozwiązaniem w zasięgu wzroku jest prawdopodobnie użyć parsera Ruby i przekształcenia drzewo składniowy w zależności od potrzeb (w tym przykładzie są rekurencyjnie zstępującej do drzewa połączeń, gromadzenie połączenia do listy):

# gem install ruby_parser 
# gem install awesome_print 
require 'ruby_parser' 
require 'ap' 

def calls_as_list code 
    tree = RubyParser.new.parse(code) 

    t = tree 
    calls = [] 

    while t 
     # gather arguments if present 
     args = nil 
     if t[3][0] == :arglist 
      args = t[3][1..-1].to_a 
     end 
     # append all information to our list 
     calls << [t[2].to_s, args] 
     # descend to next call 
     t = t[1] 
    end 

    calls.reverse 
end 

p calls_as_list "foo.bar.size.split('.').last" 
#=> [["foo", []], ["bar", []], ["size", []], ["split", [[:str, "."]]], ["last", []]] 
p calls_as_list "puts 3, 4" 
#=> [["puts", [[:lit, 3], [:lit, 4]]]] 

I pokazać drzewo parsującej jakiegokolwiek wejścia:

ap RubyParser.new.parse("puts 3, 4")