Home > database >  JS Regex to match number with only one comma
JS Regex to match number with only one comma

Time:11-26

I need to find out all numbers with exactly one comma. I've got this regex,

[\d ,] 

but it matches all numbers no matter how much commas is in the number.

So, in this text

lorem 49 877 989 888,33 ipsum 1,2,3 dfgdfgdf 1,222

it should match only first and last number:

49 877 989 888,33 
1,222

and NOT this

1,2,3

CodePudding user response:

You can use

\b(?<!\d,)(?:\d{1,3}(?: \d{3})*|\d ),\d \b(?!,\d)

See the regex demo.

const text = "lorem 49 877 989 888,33 ipsum 1,2,3 dfgdfgdf 1,222";
console.log(text.match(/\b(?<!\d,)(?:\d{1,3}(?: \d{3})*|\d ),\d \b(?!,\d)/g));

Details:

  • \b - a word boundary
  • (?<!\d,) - a negative lookbehind that fails the match if there is a digit and a comma immediately to the left of the current location
  • (?: - start of a non-capturing group:
    • \d{1,3} - one to three digits
    • (?: \d{3})* - zero or more repetitions of a space and three digits (replace the space with \s to match any whitespace chars)
    • | - or
    • \d - any one or more digits
  • , - a comma
  • \d - one or more digits
  • \b - a word boundary
  • (?!,\d) - a negative lookahead that fails the match if there is a comma and a digit immediately to the right of the current location.

If you do not want to use a regex with a lookbehind so that the pattern could be used in old/legacy browsers, use a common workaround:

(\d,)?\b(?:\d{1,3}(?: \d{3})*|\d ),\d \b(?!,\d)

and filter out all matches where Group 1 is not empty. See regex demo #2.

var text = "lorem 49 877 989 888,33 ipsum 1,2,3 dfgdfgdf 1,222";
var regex = /(\d,)?\b(?:\d{1,3}(?: \d{3})*|\d ),\d \b(?!,\d)/g;
var results = [], m;
while (m = regex.exec(text)) {
  if (m[1] === undefined) results.push(m[0])
}
console.log(results);

CodePudding user response:

We can use an approach with two regex patterns. First match on:

\b\d (?:[ ,]?\d )*\b

And then filter on only numbers with at most one comma.

Sample script:

var input = "lorem 49 877 989 888,33 ipsum 1,2,3 dfgdfgdf 1,222";
var nums = input.match(/\b\d (?:[ ,]?\d )*\b/g)
                .filter(x => !x.match(/,.*,/));
console.log(nums);

CodePudding user response:

Can't do it in one line code, this is my solution:

let input = 'lorem 49 877 989 888,33 ipsum 1,2,3 dfgdfgdf 1,222'

let numbers = []
let words = input.split(/\s /)
words.forEach(function(w)
{
        let nums = w.match(/\d (?:[,\d] )?/)
        if(nums)
        {
                let commas = nums[0].match(/,/g)
                if(commas)
                        commas = commas.length
                else
                        commas = 0
                if(commas<2)
                        numbers.push(nums[0])
        }
})

console.log(numbers)

Output:

[ '49', '877', '989', '888,33', '1,222' ]

CodePudding user response:

My two cents using zero width lookbehind:

(?<!\d\s*,?)\d (?:\s\d )*,\d (?!,?\s*\d)

See an online demo


  • (?<!\d\s*,?) - Assert position is not preceded by a digit with 0 space chars and an optional comma;
  • \d (?:\s\d )*,\d - Match 1 digits, an non-capture group matched 0 times to allow for space delimited numbers before matching a comma and 1 more digits;
  • (?!,?\s*\d) - Assert position is not followed by an optional comma, 0 whitespace chars and another digit.

var s_in = "lorem 49 877 989 888,33 ipsum 1,2,3 dfgdfgdf 1,222";
var s_out = s_in.match(/(?<!\d\s*,?)\d (?:\s\d )*,\d (?!,?\s*\d)/g);
console.log(s_out);

  • Related