Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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.

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 ].

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top