From: Rick DeNatale Date: 2007-05-03T08:06:13+09:00 Subject: Re: Inverse scanf: finding format specifers of existing fields On 5/2/07, Bil Kleb wrote: > Hi, > > I have files full of numbers that I need to twiddle, > but the format of the numbers cannot change[1], e.g., > > '0.4577' -> '0.7728' > > or > > '-2.345e-02' -> ' 1.232e-03' > > Using scanf for the output seems to be the solution to > the second half of the problem, but how does one derive > the format specifier string of the input fields, which vary? > Bill, How's this for a start? I wrote it leaning towards clarity vs. conciseness. rick@frodo:/public/rubyscripts$ cat number_format.rb class String def to_number_format m = match(%r{^([ ]*)([+-]?)(.*)$}) leading_blanks, sign, rest = m[1], m[2], m[3] plus_flag = sign == '+' ? sign : '' case rest when %r{^([\d]\.([\d]+)([eE])[+-][\d]+)(.*)$} # exponentiated float entirety, frac_part, e_or_E, exponent, suffix = $1, $2, $3, $4, $5 entirety = leading_blanks << entirety "%#{entirety.length}.#{frac_part.length}#{e_or_E}#{suffix}" when %r{^([\d]+\.([\d]*))(.*)$} # simple float entirety, frac_part, suffix = $1, $2, $3 zero = frac_part.match(/00$/) ? '0' : '' "%#{zero}#{entirety.length}.#{frac_part.length}f#{suffix}" when %r{^(0[\d]+)([^e.]*)$} # zero padded integer digits, suffix = $1, $2 "#{leading_blanks}%#{plus_flag}0#{digits.length}d#{$suffix}" when %r{^([\d]+)([^e.]*)$} # whitespace padded integer digits, suffix = $1, $2 digits = leading_blanks << digits "%#{digits.length}d#{suffix}" else nil end end end x = '0.4577' puts x puts x.to_number_format puts x.to_number_format % x.to_f puts(x.to_number_format % 0.7728) puts (x.to_number_format % x.to_f) == x puts x = '-2.345e-02' puts x puts x.to_number_format puts(x.to_number_format % x.to_f) puts(x.to_number_format % 1.232e-03) puts (x.to_number_format % x.to_f) == x puts x = '12345' puts x puts x.to_number_format puts(x.to_number_format % x.to_i) puts(x.to_number_format % 765) puts (x.to_number_format % x.to_f) == x puts x = ' 00012345' puts x puts x.to_number_format puts(x.to_number_format % x.to_i) puts(x.to_number_format % 765) puts (x.to_number_format % x.to_i) == x puts x = ' 12345' puts x puts x.to_number_format puts(x.to_number_format % x.to_i) puts(x.to_number_format % 765) puts (x.to_number_format % x.to_i) == x rick@frodo:/public/rubyscripts$ ruby number_format.rb 0.4577 %6.4f 0.4577 0.7728 true -2.345e-02 %9.3e -2.345e-02 1.232e-03 true 12345 %5d 12345 765 true 00012345 %08d 00012345 00000765 true 12345 %7d 12345 765 true -- Rick DeNatale My blog on Ruby http://talklikeaduck.denhaven2.com/