Domanda

I have a text file with comma delimited fields. The numeric field values are double quoted and formatted in Italian locale like "4.294.967.295,000". Here are sample data from the text file:

Saldo contabile:,"1.123.456,89"
Saldo disponibile:,"1.123.456,89"

18/03/2014,16/03/2014,"-22,00","-23.122,00",EUR,AUT,-,43,PDPOT,"PAGOBANCOMAT            16/03/14,ORE 11:17,TESS.800999999                 FARMACIA XXXYYY DR.ZZZ",-

1

I want to change the format into the US-English locale like "4,294,967,295.00" by swapping "," with ".", preferably by using sed, or vim, or Ruby. Swapping dot and comma is not a solution because comma is also used as the as the delimiter between fields.

So far I was able to match fields in which it is necessary to make the replacement: sample regexp to match numeric fields

How can I swap points and commas only within numeric fields?

È stato utile?

Soluzione 2

I'd recommend a language with a real CSV parser. So ruby, not awk:

echo 'Saldo contabile:,"1.123.456,89"
Saldo disponibile:,"1.123.456,89"'|
ruby -rcsv -ne '
  row = CSV.parse_line($_)
  row.each {|elem| elem.tr!(",.",".,") if elem.match(/^-?[0-9,.]+$/)} 
  puts CSV.generate_line(row)
'
Saldo contabile:,"1,123,456.89"
Saldo disponibile:,"1,123,456.89"

Ruby has a -i option that works like sed -i to update the file inplace, if you need that.

Altri suggerimenti

Probably not the answer you expect: You could make two steps one after the other.

In Ruby: s.gsub('.','').gsub(',','.')

This action could be integrated in a CSV-parser.

Example:

require 'csv'
data = <<data
Saldo contabile:,"1.123.456,89"
Saldo disponibile:,"1.123.456,89"
Saldo disponibile:,"-1.123.456,89"
data
CSV::Converters[:num_it] = ->(s) {(s =~ /[-\d\.,]+/) ? (s.gsub('.','').gsub(',','.').to_f) : s}
#Alternative version with String#tr
#CSV::Converters[:num_it] = ->(s) {(s =~ /[-\d\.,]+/) ? (s.tr('.,', '_.').to_f) : s}
csv = CSV(data, :headers => false, :col_sep => ',',
                #~ :converters => :all
                :converters => [
                    *CSV::Converters.keys,
                    :num_it
                ]
            )
csv.each do |row|
  #~ p row
  print row[0];print " %.2f\n" % row[1]
end

Result:

Saldo contabile: 1123456.89
Saldo disponibile: 1123456.89
Saldo disponibile: -1123456.89

Beside the version with two sub, you could also try one String#gsub with the hash or block-version:

s = "1.123.456,89"
p s.gsub(/[\.,]/, {'.' => ',', ',' => '.'}) #-> "1,123,456.89"
p s.gsub(/[\.,]/){|hit| hit == '.' ?  ',' : '.'} #-> "1,123,456.89"
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top