Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find only numeric values without mix of alphabet values using regex?

I have one equation: +8x2+10y2-99+5=99. I need separate the numeric values only without mix of alphabetic characters. I used the regex str.match(/[0-9]/g) to get the all numeric values, but for the equation above, the results should be -99,5,99.

like image 451
prasanth Avatar asked May 14 '16 15:05

prasanth


2 Answers

You can use an optional hyphen and word boundaries to match only numbers from given expressions:

var str = '+8x2+10y2-99+5=99';

var matches = str.match(/-?\b\d+\b/g);

document.writeln('<pre>' + matches.join(',') + '</pre>');

Output:

-99,5,99

RegEx Demo

like image 143
anubhava Avatar answered Oct 06 '22 22:10

anubhava


Riffing on your original approach, we can build up to a solid solution and learn a little about how some additional regex features work.

First, let's add support for separating the alphabets. That can be done by using the \b metacharacter, which gives a virtual match only at the transition point between a word character and a non-word character (or a word character and the beginning or end of the input text). The definition of what constitutes a word character differs between regex implementations, but it's often similar to the character class [a-zA-Z0-9_]; check your language reference documentation for the details.

var results = '+8x2+10y2-99+5=99'.match(/\b[0-9]+\b/g);

document.writeln('<pre>' + results.join(',') + '</pre>');

This produces the following output, which is very close, but fails to pick up the '-':

99,5,99

Next stop: get the dash. This is only a single character change, and we add the '-' character at the end of the [0-9] character class. The '-' has special powers in a character class, which requires either escaping the '-' or using the special rule that it has no powers at the end of the character class; I don't like escaping when I don't have to, so at the end it goes. Now for the example:

var results = '+8x2+10y2-99+5=99'.match(/\b[0-9-]+\b/g);

document.writeln('<pre>' + results.join(',') + '</pre>');

And viola! The results are in and they are good:

-99,5,99

However, we can improve on this regex. The first improvement is to use the \d metacharacter to replace the way-too-long 0-9 range in the character class. Using this technique represents a 33.333% savings in keys typed, and will impress your friends, colleagues, and regex wonks everywhere:

var results = '+8x2+10y2-99+5=99'.match(/\b[\d-]+\b/g);

document.writeln('<pre>' + results.join(',') + '</pre>');

Just checking, and yes, we have the same results:

-99,5,99

Finally, we'll fix a little niggling issue that we created when we added the '-' support a couple of steps back. The issue is that this approach can actually result in some false (or improper) match results.

For example, when the input contains a valid number minus another valid number, the previous solutions would return them both as one single result. We'll test that and then separate the '-' to be matched only as a prefix to a valid number. To test this, we have to change up the input just a bit (change the "10y2" to just "10") and then test the previous ("bad") and new ("good") solutions:

var text = '+8x2+10-99+5=99';

var bad_results = text.match(/\b[\d-]+\b/g);
var good_results = text.match(/\b-?\d+\b/g);

document.writeln('<pre> Bad: ' + bad_results.join(',') + '</pre>');
document.writeln('<pre> Good: ' + good_results.join(',') + '</pre>');

The result from this is:

Bad: 10-99,5,99
Good: 10,-99,5,99

Clearly, this is a better approach. And with that, we have our final solution. Be well and regex wisely!

like image 39
Michael Gaskill Avatar answered Oct 06 '22 21:10

Michael Gaskill