Hung Le
Hung Le

Reputation: 23

Split string to array with ruby

I have the string: "how to \"split string\" to \"following array\"" (how to "split string" to "following array").

I want to get the following array:

["how", "to", "split string", "to", "following array"]

I tried split(' ') but the result is:

["how", "to", "\"split", "string\"", "to", "\"following", "array\""]

Upvotes: 0

Views: 1527

Answers (2)

JWT
JWT

Reputation: 407

With x as your string:

x.split(?").each_slice(2).flat_map{|n, q| a = n.split; (a << q if q) || a }

When you split on quotes, you know for certain that each string in the array goes: non-quoted, quoted, non-quoted, quoted, non-quoted etc...

If we group these into pairs then we get one of the following two scenarios:

  1. [ "non-quoted", "quoted" ]
  2. [ "non-quoted", nil ] (only ever for the last pair of an unbalanced string)

For example 1, we split nq and append q
For example 2, we split nq and discard q
i.e.: a = n.split; (a << q if q) || q

Then we join all the pairs back up (the flat part of flat_map)

Upvotes: 0

ndnenkov
ndnenkov

Reputation: 36101

x.split('"').reject(&:empty?).flat_map do |y|
  y.start_with?(' ') || y.end_with?(' ') ? y.split : y
end

Explanation:

  • split('"') will partition the string in a way that non-quoted strings will have a leading or trailing space and the quoted ones wouldn't.
  • The following flat_map will further split an individual string by space only if it falls in the non-quoted category.
  • Note that if there are two consecutive quoted strings, the space in between will be it's own string after the first space and will completely disappear after the second. Aka:

    'foo "bar" "baz"'.split('"') # => ["foo ", "bar", " ", "baz"]
    ' '.split # => []
    
  • The reject(&:empty?) is needed in case we start with a quoted string as

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

Upvotes: 3

Related Questions