22

これはRuby1.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\(\)]/)

ここでは、グループを使用(\.)して分割しようとしていますが、これは適切なアプローチではないようです。

4

4 に答える 4

35

私はこれがそれをするだろうと思います:

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

正規表現についてどれだけ知っているかはわかりませんが、(?=[\w])「次の文字が文字の種類の文字である場合にのみドットに一致する」という先読みです。先読みは、一致するテキストを実際に取得することはありません。それはただ「見える」だけです。したがって、結果はまさにあなたが探しているものです:

> a.split(/\.(?=[\w])/)
 => ["foo", "bar", "size", "split('.')", "last"] 
于 2012-10-11T12:37:16.607 に答える
8

正規表現ではそれほど遠くないのではないかと思います。たとえば、次の式を考えてみましょう(これも有効な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")
于 2012-10-11T13:08:20.710 に答える
4
a = "foo.bar.size.split('.').last"
p a.split(/(?<!')\.(?!')/)

#=> ["foo", "bar", "size", "split('.')", "last"]

LookaheadおよびLookbehindアサーションを探しています。 http://www.regular-expressions.info/lookaround.html

于 2012-10-11T15:04:01.633 に答える
2

ここでは、rubyenvはありません。私はpythonre.split()で試しました。

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

上記の正規表現には、一重引用符の間の「ドット」のみが区切り文字として機能しないようにするために、負の先読みと後読みがあります。

もちろん、あなたが与えた例では、後読みまたは先読みのいずれかで十分です。要件に合った正しい方法を選択できます。

于 2012-10-11T12:48:09.467 に答える