3

I'm trying to use square brackets '[]' as a row separator in a CSV file. I must use this exact format for this project (output needs to match LEDES98 law invoicing format exactly).

I'm trying to do this:

CSV.open('output.txt', 'w', col_sep: '|', row_sep: '[]') do |csv|
     #Do Stuff
end

But Ruby won't take row_sep: '[]' and throws this error:

lib/ruby/1.9.1/csv.rb:2309:in `initialize': empty char-class: /[]\z/ (RegexpError)

I've tried escaping the characters with /'s, using double quotes, etc, but nothing has worked yet. What's the way to do this?

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Dan
  • 641
  • 9
  • 25
  • I don't think you can do it with the CSV class as it is. You may need to do two part processing. First, use `col_sep` and not `row_sep`. Then rewrite each line by wrapping it with `[ ... ]`. – Candide Jan 08 '13 at 08:56
  • could you add a sample of the data ? – peter Jan 08 '13 at 16:10

3 Answers3

1

The problem is in CSV#encode_re: the parameter row_sep: "|[]\n" is converted to a Regexp.

What can redefine this method:

class CSV
  def encode_re(*chunks)
    encode_str(*chunks)
  end
end
CSV.open('output.txt', 'w', col_sep: '|', row_sep: "|[]\n"
  ) do |csv|
   csv << [1,2,3]
   csv << [4,5,6]
end

The result is:

1|2|3|[]
4|5|6|[]

I found no side effect, but I don't feel comfortble to redefine CSV, so I would recommend to create a new CSV-variant:

#Class to create LEDES98
class LEDES_CSV < CSV
  def encode_re(*chunks)
    encode_str(*chunks)
  end
end
LEDES_CSV.open('output.txt', 'w', col_sep: '|', row_sep: "|[]\n"
  ) do |csv|
   csv << [1,2,3]
   csv << [4,5,6]
end

Then you can use the 'original' CSV and for LEDES-files you can use the LEDES_CSV.

knut
  • 27,320
  • 6
  • 84
  • 112
0

Given an input string of the form

s = "[cat][dog][horsey\nhorse]"

you could use something like

s.scan(/\[(.*?)\]/m).flatten

which would return ["cat", "dog", "horsey\nhorse"] and process that with CSV module.

EdvardM
  • 2,934
  • 1
  • 21
  • 20
0

I just tried

require 'csv'
#Create LEDES98
CSV.open('output.txt', 'w', col_sep: '|', row_sep: '[]') do |csv|
     csv << [1,2,3]
     csv << [4,5,6]
end

and I got

1|2|3[]4|5|6[]

Which csv/ruby-version do you use? My CSV::VERSION is 2.4.7, my ruby version is 1.9.2p290 (2011-07-09) [i386-mingw32].

Another remark: If I look at the example files in http://www.ledes.org/ then you need additional newlines. I would recommed to use:

require 'csv'
#Create LEDES98
CSV.open('output.txt', 'w', col_sep: '|', row_sep: "[]\n") do |csv|
     csv << [1,2,3,nil]
     csv << [4,5,6,nil]
end

Result:

1|2|3|[]
4|5|6|[]

The additional nils gives you the last | before the [].


I tested on another computer with ruby 1.9.3p194 (2012-04-20) [i386-mingw32] and get the same error.

I researched a bit and can isolate the problem:

p "[]"      #[]
p "\[\]"    #[]     <--- Problem
p "\\[\\]"  #\\[\\]

You can't mask the [. If you mask it once, Ruby produces [ (without the mask sign). If you mask it twice, you mask only the \, not the ].

knut
  • 27,320
  • 6
  • 84
  • 112
  • Ruby version 1.9.3p194 (2012-04-20 revision 35410) [x86_64-darwin11.4.0] – Dan Jan 10 '13 at 07:09
  • I tested on another computer with _ruby 1.9.3p194 (2012-04-20) [i386-mingw32]_ - Now I have the same error. – knut Jan 10 '13 at 19:59
  • I found a solution with a newer ruby-version. see my [other answer](http://stackoverflow.com/a/14269091/676874) – knut Jan 10 '13 at 23:22