Piotr Klosinski
Piotr Klosinski

Reputation: 25

Match all number occurrences without any letter following or preceding

What I'm trying to accomplish:

Assuming an example string:

1 this is a1 my test 1a 12 string 12.123 whatever 1

I would like to have a Regex, that would give me all the occurrences of numbers (floats included), but I want it to skip the number if a letter (or more generally: non-number) precedes or follows it. So a1 and 1a would not match.

I've been struggling with this for a while, I got to this point (not ideal, because it also catches the preceding space):

/(^|\s)\d*\.*\d+/g

But this will also catch the 1a instance... I could also set up something similar, that would skip 1a, but would catch a1...

Can I accomplish this using regex matching?

Upvotes: 1

Views: 113

Answers (4)

Vitali
Vitali

Reputation: 655

Try this expression: (?<=^|\s)[-+]?(?:[0-9]*\.[0-9]+|[0-9]+)(?=$|\s) - Regex demo

JavaScript supported: (?:^|\s)([-+]?(?:[0-9]*\.[0-9]+|[0-9]+))(?=$|\s) - Regex demo

This expression supports floating-point numbers with an optional sign.

JS does not support positive lookbehind, so it was replaced by non-capturing group. The numbers are captured by the 1st group.

Upvotes: 0

Don
Don

Reputation: 4202

For a simple, but not comprehensive solution (assuming numeric types used in the given example string, no negative numbers,scientific notation,etc.,), try this:

\d*\.*\d+

It removes the \s from your regex you developed, which matches the preceding space.

\d* will match all of the numbers (digits [0-9]).

Adding \.*\d+ will match floats (decimal followed by digits [0-9]).

Upvotes: 0

Patrick Roberts
Patrick Roberts

Reputation: 51886

This is not a regex-only answer but maybe that's a good thing, we'll see.

The regex in use here is /^[-+]?(?:\d+(?:\.\d*)?|\d*\.\d+)(?:e\d+)?$/:

var testStr = '.1 this is a1 my test +5 1a 12 string -2.4 12.123 whatever . .02e1 5e5.4 1 1.4e5 1.2.3';

console.log('matches');
console.log(...testStr
  .trim()
  .split(/\s+/g)
  .filter(word => /^[-+]?(?:\d+(?:\.\d*)?|\d*\.\d+)(?:e\d+)?$/
    .test(word)
  )
);

console.log('mismatches');
console.log(...testStr
  .trim()
  .split(/\s+/g)
  .filter(word => !/^[-+]?(?:\d+(?:\.\d*)?|\d*\.\d+)(?:e\d+)?$/
    .test(word)
  )
);

Upvotes: 0

anubhava
anubhava

Reputation: 785156

You can use word boundaries with this regex:

/(?:\.\d+|\b\d+(?:\.\d+)?)\b/g

RegEx Demo

Upvotes: 1

Related Questions