Venkat
Venkat

Reputation: 11

Substring within string

I need to extract from an input everything that is after a parameter.

My output should be Chocolate. I tried split, scan and the output returned two elements. Can anyone help me with this requirement?

Also, request you to let me know how to handle if my input is "-a Apple -c Chocolate -b Ball".

Upvotes: 0

Views: 70

Answers (4)

Pascal
Pascal

Reputation: 8656

If you really want everything after the marker (-c):

s = "-a Apple -b Ball -c Chocolate"
index = s.index('-c')
everything_after = s[(index + 2)..-1]
puts everything_after # => Chocolate

If you want to parse the arguments:

require 'optparse'

opts = OptionParser.new do |parser|
  parser.on('-a=s') do |v|
  end
  parser.on('-b=s') do |v|
  end
  parser.on('-c=s') do |v|
    puts "-c is #{v}"
  end
end

opts.parse("-a Apple -b Ball -c Chocolate".split(/\s/))

(you will need to specify all the flags, otherwise the parser will choke)

Or you could simply match the content with a Regexp. I think you are looking for: <ANYTHING><FLAG><ANYTHING BUT DASH><ANYTHING> where <FLAG> is '-c '

s.match(/\A.*-c\s([^-]*).*\z/) do |match|
  p match[1]
end

Upvotes: 1

Cary Swoveland
Cary Swoveland

Reputation: 110755

s = "-a Apple -b Ball -c Chocolate"

One way: calculate an index

marker = "-c"
s[s.index(marker)+marker.size+1..-1]
  #=> "Chocolate" 

marker = "-b"
s[s.index(marker)+marker.size+1..-1]
  #=> "Ball -c Chocolate" 

marker = "-a"
s[s.index(marker)+marker.size+1..-1]
  #=> "Apple -b Ball -c Chocolate" 

Another way: use a regex

`\K` in the regex below means "forget everything matched so far".

marker = "-c"
s[/#{marker}\s+\K.*/]
  #=> "Chocolate" 

marker = "-b"
s[/#{marker}\s+\K.*/]
  #=> "Ball -c Chocolate" 

marker = "-a"
s[/#{marker}\s+\K.*/]
  #=> "Apple -b Ball -c Chocolate" 

Consider the regex for one of these markers.

marker = "-a"
r = /
    #{marker}   # match the contents of the variable 'marker'
    \s+         # match > 0 whitespace chars
    \K          # forget everything matched so far
    .*          # match the rest of the line
    /x          # free-spacing regex definition mode
  #=> /
  #   -a          # match the contents of the variable 'marker'
  #   \s+         # match > 0 whitespace chars
  #   \K          # forget everything matched so far
  #   .*          # match the rest of the line
  #   /x 
s[r]
  #=> "Apple -b Ball -c Chocolate"

But if you really want just the text between markers

I will construct a hash with markers as keys and text as values. First, we will use the following regex to split the string.

r = /
      \s*     # match >= 0 spaces
      \-      # match hypen
      (       # begin capture group 1
        [a-z] # match marker
      )       # end capture group 1
        \s*   # match >= 0 spaces
      /x      # free-spacing regex definition mode

h = s.split(r).drop(1).each_slice(2).to_h
  #=> {"a"=>"Apple", "b"=>"Ball", "c"=>"Chocolate"} 

With this hash we can retrieve the text for each marker.

h["a"]
  #=> "Apple" 
h["b"]
  #=> "Ball" 
h["c"]
  #=> "Chocolate" 

The steps to create the hash are as follows.

a = s.split(r)
  #=> ["", "a", "Apple", "b", "Ball", "c", "Chocolate"] 

Notice that, by putting [a-z] within a capture group in the regex, "a", "b" and "c" are included in the array a. (See String#split, third paragraph.)

b = a.drop(1)
  #=> ["a", "Apple", "b", "Ball", "c", "Chocolate"] 
c = b.each_slice(2)
  #=> #<Enumerator: ["a", "Apple", "b", "Ball", "c", "Chocolate"]:each_slice(2)> 

We can see the elements of the enumerator c by converting it to an array:

c.to_a
  #=> [["a", "Apple"], ["b", "Ball"], ["c", "Chocolate"]] 

Lastly,

c.to_h
  #=> {"a"=>"Apple", "b"=>"Ball", "c"=>"Chocolate"} 

Upvotes: 0

Dharam Gollapudi
Dharam Gollapudi

Reputation: 6438

Assuming that the input is the command line arguments passed to a ruby script, try:

ARGV[ARGV.index("-c") + 1]

Explanation:

ARGV is an array that includes all the arguments passed to a ruby script. Array#index returns the index of the first object in self.

Refer to Array#index for more info.

Upvotes: 0

tadman
tadman

Reputation: 211740

You can use the OptionParser library to do this:

require 'optparse'

arguments = { }

opts = OptionParser.new do |parser|
  parser.on('-a=s') do |v|
    arguments[:a] = v
  end
  parser.on('-b=s') do |v|
    arguments[:b] = v
  end
  parser.on('-c=s') do |v|
    arguments[:c] = v
  end
end

opts.parse("-a Apple -b Ball -c Chocolate".split)

arguments
# => {:a=>"Apple", :b=>"Ball", :c=>"Chocolate"}

It's quite flexible in how it works, so you can define a lot of options and how they're interpreted.

Upvotes: 2

Related Questions