Ruby Code Quiz - How can I parse quoted values with String#split?


(Gerald Bauer) #1

Hello,

   can anyone help out. I cannot get this to work.
I try to parse the line ‹"1", "2" , "3"›.
Ideally single or double quotes don't matter ‹"1", '2' , "3"›.

Any insight appreciated. Cheers. Prost.

The code:

parts = parse.split(@col_sep_split_separator, -1)
     if parts.empty?
       if in_extended_col
         csv[-1] << @col_sep # will be replaced with a @row_sep
after the parts.each loop
       else
         csv << nil
       end
     end

     # This loop is the hot path of csv parsing. Some things may be non-dry
     # for a reason. Make sure to benchmark when refactoring.
     parts.each do |part|
       if in_extended_col
         # If we are continuing a previous column
         if part.end_with?(@quote_char) && part.count(@quote_char) % 2 != 0
           # extended column ends
           csv.last << part[0..-2]
           if csv.last.match?(@parsers[:stray_quote])
             raise MalformedCSVError.new("Missing or stray quote",
                                         lineno + 1)
           end
           csv.last.gsub!(@double_quote_char, @quote_char)
           in_extended_col = false
         else
           csv.last << part << @col_sep
         end
       elsif part.start_with?(@quote_char)
         # If we are starting a new quoted column
         if part.count(@quote_char) % 2 != 0
           # start an extended column
           csv << (part[1..-1] << @col_sep)
           in_extended_col = true
         elsif part.end_with?(@quote_char)
           # regular quoted column
           csv << part[1..-2]
           if csv.last.match?(@parsers[:stray_quote])
             raise MalformedCSVError.new("Missing or stray quote",
                                         lineno + 1)
           end
           csv.last.gsub!(@double_quote_char, @quote_char)
         elsif @liberal_parsing
           csv << part
         else
           raise MalformedCSVError.new("Missing or stray quote",
                                       lineno + 1)
         end
       elsif part.match?(@parsers[:quote_or_nl])
         # Unquoted field with bad characters.
         if part.match?(@parsers[:nl_or_lf])
           message = "Unquoted fields do not allow \\r or \\n"
           raise MalformedCSVError.new(message, lineno + 1)
         else
           if @liberal_parsing
             csv << part
           else
             raise MalformedCSVError.new("Illegal quoting", lineno + 1)
           end
         end
       else
         # Regular ole unquoted field.
         csv << (part.empty? ? nil : part)
       end
     end