# Currency formatting with regexp

**URL:** <https://rubytalk.org/t/currency-formatting-with-regexp/16413>\
**Category:** ruby-talk\
**Created:** [11 February 2005 18:04 UTC](https://rubytalk.org/t/currency-formatting-with-regexp/16413 "2005-02-11T18:04:35Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jim\_Van\_Fleet](https://avatars.discourse-cdn.com/v4/letter/j/3bc359/32.png) [@Jim\_Van\_Fleet](https://rubytalk.org/u/Jim_Van_Fleet)\
**Post date:** [11 February 2005 18:04 UTC](https://rubytalk.org/t/currency-formatting-with-regexp/16413/1 "2005-02-11T18:04:35Z")

</div>

Hi, all, this is my first post to Ruby-talk, so please be kind-- if that's not your natural disposition.

I'm looking to work up some code that turns floats into string-based currency values.

I've got an implementation working that's pretty ungodly. It looks a lot like I would program it in Java. Naturally, once I finished, I found some Perl suggestion that looks like this:

sub commify {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;my $text = reverse $\_[0];  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$text =~ s/(\d\d\d)(?=\d)(?!\d\*\.)/$1,/g;  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return scalar reverse $text;  
}

I am a regexp noob. I experimented with using gsub and this regular expression, but I can't seem to get anywhere. The closest I've come replaces the first comma but then eliminates the rest of the number.

Can someone help me figure out what's going on-- or point me to where this is already available in Ruby? (Pickaxe II references neither money nor currency, and I don't really want to install extensions just for this functionality.)

Thanks so much,

Jim

---

<div class="post-metadata">

**Author:** ![James\_Edward\_Gray\_II](https://avatars.discourse-cdn.com/v4/letter/j/ea5d25/32.png) [@James\_Edward\_Gray\_II](https://rubytalk.org/u/James_Edward_Gray_II)\
**Post date:** [11 February 2005 18:25 UTC](https://rubytalk.org/t/currency-formatting-with-regexp/16413/2 "2005-02-11T18:25:20Z")

</div>

Here's a direct Ruby translation:

def commify( number )  
&nbsp;&nbsp;text = number.to\_s.reverse  
&nbsp;&nbsp;text.gsub!(/(\d\d\d)(?=\d)(?!\d\*\.)/, '\1,')  
&nbsp;&nbsp;text.reverse  
end

Hope that helps.

James Edward Gray II

> **···**
>
> On Feb 11, 2005, at 12:04 PM, Jim Van Fleet wrote:
> 
> > sub commify {  
> > &nbsp;&nbsp;&nbsp;&nbsp;my $text = reverse $\_[0];  
> > &nbsp;&nbsp;&nbsp;&nbsp;$text =~ s/(\d\d\d)(?=\d)(?!\d\*\.)/$1,/g;  
> > &nbsp;&nbsp;&nbsp;&nbsp;return scalar reverse $text;  
> > }

---

<div class="post-metadata">

**Author:** ![Austin\_Ziegler5](https://yyz1.discourse-cdn.com/flex029/user_avatar/rubytalk.org/austin_ziegler5/32/1985_2.png) [@Austin\_Ziegler5](https://rubytalk.org/u/Austin_Ziegler5)\
**Post date:** [11 February 2005 20:17 UTC](https://rubytalk.org/t/currency-formatting-with-regexp/16413/3 "2005-02-11T20:17:01Z")

</div>

Might I suggest looking at Gavin Sinclair's "extensions" package? This  
has some code that I wrote and released under an MIT-style licence to  
format numbers with commas and has a \*lot\* of different formatting  
capabilities.

-austin

> **···**
>
> On Sat, 12 Feb 2005 03:04:35 +0900, Jim Van Fleet \<jim@jimvanfleet.com\> wrote:
> 
> > I'm looking to work up some code that turns floats into string-based  
> > currency values.
> 
> --  
> Austin Ziegler \* halostatue@gmail.com  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\* Alternate: austin@halostatue.ca

---

<div class="post-metadata">

**Author:** ![Jim\_Van\_Fleet](https://avatars.discourse-cdn.com/v4/letter/j/3bc359/32.png) [@Jim\_Van\_Fleet](https://rubytalk.org/u/Jim_Van_Fleet)\
**Post date:** [11 February 2005 19:46 UTC](https://rubytalk.org/t/currency-formatting-with-regexp/16413/4 "2005-02-11T19:46:02Z")

</div>

James Edward Gray II wrote:

> **···**
>
> > On Feb 11, 2005, at 12:04 PM, Jim Van Fleet wrote:
> > 
> > Here's a direct Ruby translation:
> > 
> > def commify( number )  
> > &nbsp;&nbsp;&nbsp;&nbsp;text = number.to\_s.reverse  
> > &nbsp;&nbsp;&nbsp;&nbsp;text.gsub!(/(\d\d\d)(?=\d)(?!\d\*\.)/, '\1,')  
> > &nbsp;&nbsp;&nbsp;&nbsp;text.reverse  
> > end
> > 
> > Hope that helps.
> 
> It sure did, and cut my LOC count in half.
> 
> What does \1 signify, exactly? Is this the active matched section of the source string at the time?
> 
> Cheers,
> 
> Jim

---

<div class="post-metadata">

**Author:** ![Mark\_Hubbart1](https://avatars.discourse-cdn.com/v4/letter/m/a3d4f5/32.png) [@Mark\_Hubbart1](https://rubytalk.org/u/Mark_Hubbart1)\
**Post date:** [12 February 2005 00:32 UTC](https://rubytalk.org/t/currency-formatting-with-regexp/16413/5 "2005-02-12T00:32:49Z")

</div>

golf?

def commify(num)  
&nbsp;&nbsp;num.to\_s.reverse.scan(/..?.?/).join(",").reverse  
end

... sorry, couldn't resist. Weak character.

cheers,  
Mark

> **···**
>
> On Sat, 12 Feb 2005 03:25:20 +0900, James Edward Gray II \<james@grayproductions.net\> wrote:
> 
> > On Feb 11, 2005, at 12:04 PM, Jim Van Fleet wrote:
> > 
> > \> sub commify {  
> > \> my $text = reverse $\_[0];  
> > \> $text =~ s/(\d\d\d)(?=\d)(?!\d\*\.)/$1,/g;  
> > \> return scalar reverse $text;  
> > \> }
> > 
> > Here's a direct Ruby translation:
> > 
> > def commify( number )  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;text = number.to\_s.reverse  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;text.gsub!(/(\d\d\d)(?=\d)(?!\d\*\.)/, '\1,')  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;text.reverse  
> > end

---

<div class="post-metadata">

**Author:** ![James\_Edward\_Gray\_II](https://avatars.discourse-cdn.com/v4/letter/j/ea5d25/32.png) [@James\_Edward\_Gray\_II](https://rubytalk.org/u/James_Edward_Gray_II)\
**Post date:** [11 February 2005 20:06 UTC](https://rubytalk.org/t/currency-formatting-with-regexp/16413/6 "2005-02-11T20:06:25Z")

</div>

> It sure did, and cut my LOC count in half.

Good news.

> What does \1 signify, exactly? Is this the active matched section of the source string at the time?

In a replacement string, \N is equivalent to Perl's $N variables. Outside a replacement string, you can $N variables directly. You can also use them in the block form of gsub().

Hope that clears it up.

James Edward Gray II

> **···**
>
> On Feb 11, 2005, at 1:46 PM, Jim Van Fleet wrote:

---

<div class="post-metadata">

**Author:** ![Christian\_Neukirche1](https://avatars.discourse-cdn.com/v4/letter/c/ee7513/32.png) [@Christian\_Neukirche1](https://rubytalk.org/u/Christian_Neukirche1)\
**Post date:** [12 February 2005 11:06 UTC](https://rubytalk.org/t/currency-formatting-with-regexp/16413/7 "2005-02-12T11:06:02Z")

</div>

Mark Hubbart \<discordantus@gmail.com\> writes:

> > Here's a direct Ruby translation:
> > 
> > def commify( number )  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;text = number.to\_s.reverse  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;text.gsub!(/(\d\d\d)(?=\d)(?!\d\*\.)/, '\1,')  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;text.reverse  
> > end
> 
> golf?
> 
> def commify(num)  
> &nbsp;&nbsp;num.to\_s.reverse.scan(/..?.?/).join(",").reverse  
> end
> 
> ... sorry, couldn't resist. Weak character.

IMHO, that's even easier to read...

> **···**
>
> > cheers,  
> > Mark
> 
> --  
> Christian Neukirchen \<chneukirchen@gmail.com\> [http://chneukirchen.org](http://chneukirchen.org)

---

<div class="post-metadata">

**Author:** ![Andrew\_Johnson](https://avatars.discourse-cdn.com/v4/letter/a/e9c0ed/32.png) [@Andrew\_Johnson](https://rubytalk.org/u/Andrew_Johnson)\
**Post date:** [12 February 2005 17:00 UTC](https://rubytalk.org/t/currency-formatting-with-regexp/16413/8 "2005-02-12T17:00:04Z")

</div>

[snip]

> golf?
> 
> def commify(num)  
> &nbsp;&nbsp;num.to\_s.reverse.scan(/..?.?/).join(",").reverse  
> end

That one doesn't do well with floats, which was what the poster  
was dealing with.

As an aside, the commify routine from the Perl FAQ (shown earlier)  
was actually designed as a means of commifying multiple numbers  
in a string in a single pass:

&nbsp;&nbsp;str = "123456789.987654321 and $1500.00 and 3.14159"  
&nbsp;&nbsp;p str.reverse.gsub(/(\d\d\d)(?=\d)(?!\d\*\.)/,'\1,').reverse

So if, for example, you were pulling numbers from a data source  
and creating an output string of a series of LaTeX tables, you  
could build the entire string first with the raw numbers and  
commify it all at once after the fact -- much more efficient than  
commifying each number as you build the string. (this was, in  
fact, the use-case that led to this particular solution).

regards,  
andrew

> **···**
>
> On Sat, 12 Feb 2005 09:32:49 +0900, Mark Hubbart \<discordantus@gmail.com\> wrote:
> 
> --  
> Andrew L. Johnson [http://www.siaris.net/](http://www.siaris.net/)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;In theory, there's no difference between  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;theory and practice, but in practice there is!

---

<div class="post-metadata">

**Author:** ![W\_James](https://avatars.discourse-cdn.com/v4/letter/w/e274bd/32.png) [@W\_James](https://rubytalk.org/u/W_James)\
**Post date:** [12 February 2005 21:19 UTC](https://rubytalk.org/t/currency-formatting-with-regexp/16413/9 "2005-02-12T21:19:59Z")

</div>

Andrew Johnson wrote:

> **···**
>
> > On Sat, 12 Feb 2005 09:32:49 +0900, Mark Hubbart \<discordantus@gmail.com\> \> wrote:  
> > [snip]
> > 
> > \> golf?  
> > \>  
> > \> def commify(num)  
> > \> num.to\_s.reverse.scan(/..?.?/).join(",").reverse  
> > \> end
> > 
> > That one doesn't do well with floats, which was what the poster  
> > was dealing with.
> 
> I think this works properly:
> 
> \* def commify( n )  
> \* n.to\_s.reverse.gsub(/(\d{3})(?=\d+-?$)/,'\1,').reverse  
> \* end
