How to split a string that contains a set in Ruby?

Viewed 104

I am new to the forum. I am currently trying to take this string:

65101km,Sedan,Manual,18131A,FWD,Used,5.5L/100km,Toyota,camry,SE,{AC,Heated Seats, Heated Mirrors, Keyless Entry},2010

and split it in order to get this:

65101km
Sedan
Manual
18131A
FWD
Used
5.5L/100km
Toyota
camry
SE
{AC, Heated Seats, Heated Mirrors, Keyless Entry}
2010

I have the following regex:

data_from_file.split(/[{},]+/)

But I am having a hard time keeping the set.

Any ideas?

2 Answers
str = "65101km,Sedan,Manual,18131A,FWD,Used,5.5L/100km,Toyota,camry,SE,{AC,Heated Seats, Heated Mirrors, Keyless Entry},2010"

r = /
    (?<=\A|,)  # match the beginning of the string or a comma in a positive lookbehind
    (?:        # begin a non-capture group
      {.*?}    # match an open brace followed by any number of characters,
               # lazily, followed by a closed brace
      |        # or
      .*?      # match any number of characters, lazily 
    )          # close non-capture group
    (?=,|\z)   # match a comma or the end of the string in a positive lookahead
    /x         # free-spacing regex definition mode

str.scan r
  #=> ["65101km", "Sedan", "Manual", "18131A", "FWD", "Used", "5.5L/100km", "Toyota",
  #    "camry", "SE", "{AC,Heated Seats, Heated Mirrors, Keyless Entry}", "2010"]

Two notes follow. I'll illustrate these with a simpler string.

str = "65101km,Sedan,{AC,Heated Seats},2010"

1. {.*?} must precede .*? in (?:{.*?}|.*?)

If

r = /(?<=\A|,)(?:.*?|{.*?})(?=,|\z)/

then

str.scan r
  #=> ["65101km", "Sedan", "{AC", "Heated Seats}", "2010"]

2. The matches .* must be lazy (aka non-greedy)

If

r = /(?<=\A|,)(?:{.*?}|.*)(?=,|\z)/

then

str.scan r
  #=> ["65101km,Sedan,{AC,Heated Seats},2010"]

If

r = /(?<=\A|,)(?:{.*}|.*?)(?=,|\z)/

then

"65101km,Sedan,{AC,Heated Seats},2010,{starter motor, pneumatic tires}".scan r
  #=> ["65101km", "Sedan", "{AC,Heated Seats},2010,{starter motor, pneumatic tires}"]

You may use

s.scan(/(?:{[^{}]*}|[^,])+/)

See the Rubular and Regex.101 demos.

Pattern details

  • (?: - start of a non-capturing group:
    • {[^{}]*} - {, 0 or more chars other than { and } and then }
  • | - or
    • [^,] - any 1 char other than ,
  • )+ - repeated 1 or more times.
Related