A small, fast, and (I think) complete csv parser.

Now handles newlines within fields.
A comma is now the default field-separator.


|  class Array
|    def to_csv
|      ",".is_fs   if $csv_fs.nil?
|      s = ''
|      self.map { |item|
|        str = item.to_s
|        # Quote the string if it contains the field-separator or
|        # a " or a newline, or if it has leading or trailing
whitespace.
|        if str.index($csv_fs) or /^\s|"|\n|\s$/.match(str)
|          str = '"' + str.gsub( /"/, '""' ) + '"'
|        end
|        str
|      }.join($csv_fs)
|    end
|    def unescape
|      self.map{|x| x.gsub( /""/, '"' ) }
|    end
|  end
|
|  class String
|    # Set regexp for parse_csv.
|    # self is the field-separator, which must be
|    # a single character.
|    def is_fs
|      $csv_fs = self
|      if "^" == $csv_fs
|        fs = "\\^"
|      else
|        fs = $csv_fs
|      end
|      $csv_re = \
|        ## Assumes embedded quotes are escaped as "".
|        %r{  \s*
|             (?:
|                 "(  [^"]*  (?:  "" [^"]*  )*  )"  |
|                  ( .*? )
|             )
|             \s*
|             [#{fs}]
|          }mx
|    end
|
|    def parse_string
|      (self + $csv_fs).scan( $csv_re ).flatten.compact.unescape
|    end
|  end
|
|  def get_rec( file )
|    ",".is_fs   if $csv_re.nil?
|    $csv_s = ""
|    begin
|      if file.eof?
|        raise "The csv file is malformed." if $csv_s.size>0
|        return nil
|      end
|      $csv_s += file.gets
|    end  until $csv_s.count( '"' ) % 2 == 0
|    $csv_s.chomp!
|    $csv_s.parse_string
|  end
|
|
|  while  rec = get_rec( ARGF )
|    puts "----------------"
|    puts $csv_s
|    p rec
|    puts rec.to_csv
|  
|  end