tags:

views:

278

answers:

4

Hi there,

Not sure if this is possible with a regular expression replace command, but I have an existing regex replace which will convert the last two digits of a number to the same last two digits prefixed with a full stop. This is for interfacing to a system which sends through currency values as "2500" where this represents "25.00" dollars.

My existing regex: (\d+)(\d{2})$
With replace syntax of: $1.$2

Now I have a problem though, if a value is sent through as "50" only for example, this could represent 0.50 and my regex will fail because it is searching for 1+ numeric on the left, and two numeric exactly at the end of the string.

How could I cover all these circumstances and have my regex replace replace thusly:

2500 = 25.00
500 = 5.00
50 = 0.50
5 = 0.05

Thanks again, Graham

Update: For those asking why this cannot be a divide and string format job is because I have to avoid custom programming to achieve this. It must ideally be a regex "rule" defined in a database along with other regex definitions as it's being used for a generic translation system. It will translate incoming data which could come in multiple format types, generally translating a field from "101" to "101A" for example, but in this particular case for this data type, adding values is required.

Second update: I've been thinking more about this, because I am bound to a database, would anybody see a better way than using a %wackyMoney% or some other 'token' defined in the db field and then test if we hit this token in code to apply the C# string formatting and divide?

+2  A: 

Regular expressions can't create content that doesn't exist, so you can't add a zero that isn't there. So the answer is that you shouldn't use regular expressions for this.

Your best bet would be to use (Double.Parse(value) / 100).ToString("0.00") or some such.


Since you want a generic ruleset defined in the database, I think the error here is that you're mixing numeric rules with string rules. You should probably make your database support different types of rules.

I think you should have an additional column specifying whether the value should be modified numerically or as a string. If it should be modified numerically, you could have the column currently used for the replacement specify a multiplier or some such.

If you want to take it even further, you could have a simple formula evaluator that could take something like: x / 100 + " USD". There are plenty of these available for .NET already, and it isn't very hard to make a simple one yourself either.

Blixt
I thought this was the case exactly, the content must exist first. I'll have a think, but as I responded to derobert's message, it has to be a generic, un-programmed db-defined handler ideally.
GONeale
I see. I updated my answer with some of my thoughts.
Blixt
A: 

Do you have a reason for not converting the string to a number, divide by 100, and convert back to a string with appropriate fomatting?

Bernd
+2  A: 

Why are you using a regexp for this?! There isn't going to be an easy way to do that with a single regexp, but you could do it with several (one for the 3+ digit case, one for the 2-digit case, one for the 1-digit case). But...

I don't know the exact C# syntax, but something along the lines of:

sprintf('%0.2f', «var»/100.0)

would seem to do exactly what you want as long as your numbers are small enough that your floating-point type is precise to better than 0.01. For doubles, that is well into the quadrillions.

edit 1

Since you need regexps, you can use three (in Perl syntax here, but...):

s/^(\d+)(\d{2})$/$1.$2/;   # you already have this
s/^(\d{2})$/0.$1/;         # obvious variant 1
s/^(\d{1}$/0.0$1/;         # obvious variant 2

Only one of those will match (variant 1 requires 3+ chars, variant 2 exactly 2 chars, variant 3 exactly 1 char), so you can use this if you can attach multiple regexps. I could get all that into one regexp in Perl, but I have no idea if you have full Perl regexp features (I doubt it). After all, Perl could do:

s/^(\d+)$/sprintf('%0.2f', $1/100.0)/e

but that's rather cheating. Does your regexp engine have anything similar? Or you said this is a database thing; can you use SQL's CASE conditional?

derobert
A regex is being used because this is for a generic translation system and the translation rule is being defined in the database for a set of incoming data, odd I know, in a normal circustance. But this isn't normal :)
GONeale
Wow, great response. I'm using the .NET regex engine, and I don't think we could call commands in regex like that though! Would be nice. I think however you could be definitely on to something with the semi-colon delimited regex set, I definitely have the power to be able to change the regex parser to parse multiple regex set's by semi-colon if I can't do multi-line out of the box, will take a look - thanks a lot.
GONeale
Glad to hear I've been of help.
derobert
A: 

.Net regexes can use a match evaluator to transform the match to whatever is desired:

String result = Regex.Replace(
   "test 1 test 20 test 300 test 4000 test 50000",
   @"\d+",
   (match => (Double.Parse(match.Value) / 100).ToString("0.00")));

The result is:

test 0.01 test 0.20 test 3.00 test 40.00 test 500.00
Chris R. Timmons