Ruby String split with regex

前端 未结 4 724
清酒与你
清酒与你 2021-01-03 23:16

This is Ruby 1.8.7 but should be same as for 1.9.x

I am trying to split a string for example:

a = \"foo.bar.size.split(\'.\').last\"         


        
相关标签:
4条回答
  • 2021-01-03 23:33
    a = "foo.bar.size.split('.').last"
    p a.split(/(?<!')\.(?!')/)
    
    #=> ["foo", "bar", "size", "split('.')", "last"]
    

    You are looking for Lookahead and Lookbehind assertions. http://www.regular-expressions.info/lookaround.html

    0 讨论(0)
  • 2021-01-03 23:38

    I think this would do it:

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

    I don't know how much you know about regex, but the (?=[\w]) is a lookahead that says "only match the dot if the next character is a letter kind of character". A lookahead won't actually grab the text it matches. It just "looks". So the result is exactly what you're looking for:

    > a.split(/\.(?=[\w])/)
     => ["foo", "bar", "size", "split('.')", "last"] 
    
    0 讨论(0)
  • 2021-01-03 23:43

    here I don't have ruby env. I tried with python re.split().

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

    the regex above has negative lookahead AND lookbehind, to make sure only the "dot" between single quotes won't work as separator.

    of course, for the given example by you, one of lookbehind or lookahead is sufficient. you can choose the right way for your requirement.

    0 讨论(0)
  • 2021-01-03 23:47

    I'm afraid that regular expressions won't take you very far. Consider for example the following expressions (which are also valid Ruby)

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

    The problem is, that the list of calls is actually a tree of calls. The easiest solution in sight is probably to use a Ruby parser and transform the parse tree according to your needs (in this example we are recursively descending into the call tree, gathering the calls into a list):

    # 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]]]]
    

    And to show the parse tree of any input:

    ap RubyParser.new.parse("puts 3, 4")
    
    0 讨论(0)
提交回复
热议问题