Ruby Regexp group matching, assign variables on 1 line

前端 未结 5 835
旧巷少年郎
旧巷少年郎 2020-12-07 12:38

I\'m currently trying to rexp a string into multiple variables. Example string:

ryan_string = \"RyanOnRails: This is a test\"

I\'ve mat

相关标签:
5条回答
  • 2020-12-07 13:16

    You can name your captured matches

    string = "RyanOnRails: This is a test"
    /(?<one>^.*)(?<two>:)(?<three>.*)/i =~ string
    puts one, two, three
    

    It doesn't work if you reverse the order of string and the regex.

    0 讨论(0)
  • 2020-12-07 13:19

    You don't want scan for this, as it makes little sense. You can use String#match which will return a MatchData object, you can then call #captures to return an Array of captures. Something like this:

    #!/usr/bin/env ruby
    
    string = "RyanOnRails: This is a test"
    one, two, three = string.match(/(^.*)(:)(.*)/i).captures
    
    p one   #=> "RyanOnRails"
    p two   #=> ":"
    p three #=> " This is a test"
    

    Be aware that if no match is found, String#match will return nil, so something like this might work better:

    if match = string.match(/(^.*)(:)(.*)/i)
      one, two, three = match.captures
    end
    

    Although scan does make little sense for this. It does still do the job, you just need to flatten the returned Array first. one, two, three = string.scan(/(^.*)(:)(.*)/i).flatten

    0 讨论(0)
  • 2020-12-07 13:21

    You could use Match or =~ instead which would give you a single match and you could either access the match data the same way or just use the special match variables $1, $2, $3

    Something like:

    if ryan_string =~ /(^.*)(:)(.*)/i
       first = $1
       third = $3
    end
    
    0 讨论(0)
  • 2020-12-07 13:21

    You have to decide whether it is a good idea, but ruby regexp can (automagically) define local variables for you!

    I am not yet sure whether this feature is awesome or just totally crazy, but your regex can define local variables.

    ryan_string = "RyanOnRails: This is a test"
    /^(?<webframework>.*)(?<colon>:)(?<rest>)/ =~ ryan_string
    # This defined three variables for you. Crazy, but true.
    webframework # => "RyanOnRails"
    puts "W: #{webframework} , C: #{colon}, R: #{rest}"
    

    (Take a look at http://ruby-doc.org/core-2.1.1/Regexp.html , search for "local variable").

    Note: As pointed out in a comment, I see that there is a similar and earlier answer to this question by @toonsend (https://stackoverflow.com/a/21412455). I do not think I was "stealing", but if you want to be fair with praises and honor the first answer, feel free :) I hope no animals were harmed.

    0 讨论(0)
  • 2020-12-07 13:22

    scan() will find all non-overlapping matches of the regex in your string, so instead of returning an array of your groups like you seem to be expecting, it is returning an array of arrays.

    You are probably better off using match(), and then getting the array of captures using MatchData#captures:

    g1, g2, g3 = ryan_string.match(/(^.*)(:)(.*)/i).captures
    

    However you could also do this with scan() if you wanted to:

    g1, g2, g3 = ryan_string.scan(/(^.*)(:)(.*)/i)[0]
    
    0 讨论(0)
提交回复
热议问题