BEGINNER - Convert csv file to tsv

Hi,

I am a beginner at Ruby, but I am trying to convert a csv file into a
tsv file.

The data is stored in source.csv and I need to out put it to a file in
the same directory called source.tsv, I also need to cater to output to
.txt and .xml, but starting with tsv first.

Contents of source.csv
"Firstname","Lastname","Postcode"
"John","Smith","EC1"
"Paula","James","NE13"

Output to file source.tsv
Firstname Lastname Postcode
John Smith EC1
Paula James NE13

I have started with this:

filename = ARGV.first
output_file_format = ARGV.second

file = open(filename, "r+")
valid_file_formats = ["tsv"]

if output_file_format == "tsv"
  File.open (filename, "r") do |f|
    new_file = File.open("source.tsv", "w")
                f.each_line do |line|
                fields = line.split (""\n")
                fields.each { |fd| fd = "\"#{fd}\""
                new_file.write(fields.join(",")
  end
  new_file.close
end

I understand what I need to do in my head, for each line remove the " or
, characters and replace the , character with a tab (\t), but I am
struggling with the syntax.

Using a bit of help from http://www.ruby-forum.com/topic/4097630#new

Thanks in advance

···

--
Posted via http://www.ruby-forum.com/.

I would use the csv in the stdlib to parse the csv:

http://www.ruby-doc.org/stdlib-2.0/libdoc/csv/rdoc/index.html

Jesus.

···

On Wed, Apr 24, 2013 at 10:45 AM, Jon R. <lists@ruby-forum.com> wrote:

Hi,

I am a beginner at Ruby, but I am trying to convert a csv file into a
tsv file.

The data is stored in source.csv and I need to out put it to a file in
the same directory called source.tsv, I also need to cater to output to
.txt and .xml, but starting with tsv first.

Contents of source.csv
"Firstname","Lastname","Postcode"
"John","Smith","EC1"
"Paula","James","NE13"

Output to file source.tsv
Firstname Lastname Postcode
John Smith EC1
Paula James NE13

I have started with this:

filename = ARGV.first
output_file_format = ARGV.second

file = open(filename, "r+")
valid_file_formats = ["tsv"]

if output_file_format == "tsv"
  File.open (filename, "r") do |f|
    new_file = File.open("source.tsv", "w")
                f.each_line do |line|
                fields = line.split (""\n")
                fields.each { |fd| fd = "\"#{fd}\""
                new_file.write(fields.join(",")
  end
  new_file.close
end

I understand what I need to do in my head, for each line remove the " or
, characters and replace the , character with a tab (\t), but I am
struggling with the syntax.

Using a bit of help from http://www.ruby-forum.com/topic/4097630#new

Thanks in advance

there is a lib in stdlib for parsing csv:

require "csv"

File.open("tmp.tsv","w") {|out|
  CSV.foreach("tmp.csv") {|l|
    out.write(l.join("\t")+"\n")
  }
}

···

--
Posted via http://www.ruby-forum.com/.

Jon R. wrote in post #1106750:

I wanted to try and use ruby rather than a library

Here's an example without using CSV:

File.write( 'source.tsv', File.readlines( 'source.csv' ).map do |l|
  l.chomp.gsub( /^"|"$/, '' ).gsub( /","/, "\t" )
end.join("\n") )

···

--
Posted via http://www.ruby-forum.com/.

Here's a one-liner:

ruby -r csv -e 'CSV.filter(File.open("input.csv","r"),
File.open("output.tsv","w"), :output_col_sep => "\t"){|row| row}'

···

On Wed, Apr 24, 2013 at 4:00 AM, Hans Mackowiak <lists@ruby-forum.com> wrote:

there is a lib in stdlib for parsing csv:

require "csv"

File.open("tmp.tsv","w") {|out|
  CSV.foreach("tmp.csv") {|l|
    out.write(l.join("\t")+"\n")
  }
}

--
Posted via http://www.ruby-forum.com/.

That's kind of inconsequent, isn't it? You use a CSV lib for reading but
not for writing. That way you miss good things like quoting.

I almost like tamouse's solution best - if it wasn't for the missing stream
closing. To me the most straightforward would probably be:

CSV.open("source.tsv", "wb", col_sep: "\t") do |cout|
  CSV.foreach("source.csv", col_sep: ",") do |r|
    cout << r
  end
end

Or, with CSV::filter:

File.open("source.csv") do |cin|
  File.open("source.tsv", "w") do |cout|
    CSV.filter(cin, cout, output_col_sep:"\t") {|r| r}
  end
end

Btw. I think that CSV.filter should also work without a block and then
should use it unmodified.

Kind regards

robert

···

On Wed, Apr 24, 2013 at 11:00 AM, Hans Mackowiak <lists@ruby-forum.com>wrote:

there is a lib in stdlib for parsing csv:

require "csv"

File.open("tmp.tsv","w") {|out|
  CSV.foreach("tmp.csv") {|l|
    out.write(l.join("\t")+"\n")
  }
}

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/