これはRuby 1.8.7ですが、1.9.xと同じである必要があります
たとえば、文字列を分割しようとしています:
a = "foo.bar.size.split('.').last"
# trying to split into ["foo", "bar","split('.')","last"]
基本的にそれを表すコマンドに分割します、私は正規表現でそれをしようとしていますが、方法はわかりません、アイデアは正規表現を使用することでした
a.split(/[a-z\(\)](\.)[a-z\(\)]/)
ここでは、グループ(\.)
を使用して分割しようとしていますが、これは良い方法ではないようです。
これでうまくいくと思います:
a.split(/\.(?=[\w])/)
正規表現についてどれだけ知っているかはわかりませんが、(?=[\w])
は、「次の文字が文字種の文字である場合にのみドットに一致する」という先読みです。先読みは一致するテキストを実際には取得しません。それはただ「見える」だけです。したがって、結果はまさにあなたが探しているものです:
> a.split(/\.(?=[\w])/)
=> ["foo", "bar", "size", "split('.')", "last"]
正規表現ではそれほど遠くないと思います。たとえば、次の式を検討してください(これらも有効なRubyです)。
"(foo.bar.size.split( '.' )).last"
"(foo.bar.size.split '.').last"
"(foo.bar.size.split '( . ) . .(). .').last"
問題は、呼び出しのリストが実際には呼び出しのツリーであることです。考えられる最も簡単な解決策は、おそらくRubyパーサーを使用し、必要に応じて解析ツリーを変換することです(この例では、呼び出しツリーに再帰的に下降し、呼び出しをリストに集めています)。 :
# 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]]]]
そして、任意の入力の解析ツリーを表示するには:
ap RubyParser.new.parse("puts 3, 4")
a = "foo.bar.size.split('.').last"
p a.split(/(?<!')\.(?!')/)
#=> ["foo", "bar", "size", "split('.')", "last"]
先読みと後読みのアサーションを探しています。 http://www.regular-expressions.info/lookaround.html
ここに私はRuby env。を持っていません。私はpython re.split()で試しました。).
In : re.split("(?<!')\.(?!')",a)
Out: ['foo', 'bar', 'size', "split('.')", 'last']
上記の正規表現は負の先読み[〜#〜] and [〜#〜]後読みを行い、「ドット」のみを確認しますbetween単一引用符がセパレーターとして機能しない。
もちろん、あなたが示した例では、後読みまたは先読みのいずれかで十分です。要件に合った正しい方法を選択できます。