skip to Main Content

Good morning all,

I want to make a regex that match 3 same consecutive numbers. It should match only 3 numbers in a row (separated by a space), the numbers should be identical. If there are less or more than 3 same numbers, then the output should be false

I have tried this regex /.*(d+) 1 1(?!(s1))/

console.log(/.*(d+) 1 1(?!(s1))/.test('I am 42 42 4 hey yoo')); //false --> Correct
 
console.log(/.*(d+) 1 1(?!(s1))/.test('I am 42 42 42 hey yoo')); //true --> Correct

console.log(/.*(d+) 1 1(?!(s1))/.test('I am 42 42 42 4 hey yoo')); //true --> Correct

console.log(/.*(d+) 1 1(?!(s1))/.test('I am 42 42 42 42 hey yoo')); //true --> this output should be false since there are 4 same consecutive digits

Any advice, please?

2

Answers


  1. I have assumed that the three identical strings of digits are separated by one space, that the first of this group of three is at the beginning of the string or is preceded by a space that is not preceded by the same string and the last string of this group of three is at the end of the string or is followed by a space that is not followed by the same string.

    You may attempt to match the following regular expression.

    (?: |^)(d+)(?<!(?: |^)1 1)(?: 1){2}(?=(?: |$))(?! 1(?: |$))
    

    Demo

    The regular expression can be broken down as follows. (Alternatively, hover the cursor over each part of the expression at the link to obtain an explanation of its function.)

    (?: |^)     # match a space or the beginning of the string
    (d+)       # match one or more digits and save to capture group 1
    (?<!        # begin a negative lookbehind
      (?: |^)    # match a space or the beginning of the string
      1 1      # match the content of capture group 1 twice, separated by a space
    )           # end the negative lookbehind
    (?: 1)     # match a space followed by the content of capture group 1
    {2}         # execute the preceding non-capture group twice
    (?=         # begin a positive lookahead
      (?: |$)     # match a space or the end of the string 
    )           # end the positive lookahead
    (?!         # begin a negative lookahead
       1        # match a space followed by the content of capture group 1
      (?: |$)     # match a space or the end of the string
    )           # end the negative lookahead
    

    In the above I have escaped one space that begins line to make it more prominent. Note that (?: .... ) denotes a non-capture group.

    Login or Signup to reply.
  2. In your pattern you are mixing spaces and s which matches a whitespace character, and can also match a newline.

    You can check if the first capture group value (d+) is not preceded by the same value.

    A version with word boundaries to prevent partial matches:

    b(d+)b(?<!b1 1)(?: 1){2}b(?! 1b)
    

    Regex demo

    The pattern matches:

    • b(d+)b Capture group 1, match 1+ digits between word boundaries
    • (?<!b1 1) Negative lookbehind, assert not the same number before this number
    • (?: 1){2}b Repeat 2 times a space and the group 1 value ending on a word boundary
    • (?! 1b) Negative lookahead, assert not the group 1 value to the right followed by a word boundary
    const regex = /b(d+)b(?<!b1 1)(?: 1){2}b(?! 1b)/;
    
    console.log(regex.test('I am 42 42 4 hey yoo')); //false --> Correct
     
    console.log(regex.test('I am 42 42 42 hey yoo')); //true --> Correct
    
    console.log(regex.test('I am 42 42 42 4 hey yoo')); //true --> Correct
    
    console.log(regex.test('I am 42 42 42 42 hey yoo')); //true --> this output should be false since there are 4 same consecutive digits

    Or if a lookbehind is not supported, you could match 4 or more times the same number in a row to get that out of the way, and then match 3 times the same number.

    In the result, you can check if there is a capture group 2 value:

    b(d+)(?: 1){3,}b|b(d+)(?: 2){2}b
    

    Regex demo

    const regex = /b(d+)(?: 1){3,}b|b(d+)(?: 2){2}b/;
    [
      'I am 42 42 4 hey yoo',
      'I am 42 42 42 hey yoo',
      'I am 42 42 42 4 hey yoo',
      'I am 42 42 42 42 hey yoo'
    ].forEach(s => {
      const m = s.match(regex);
      console.log(!!(m && m[2]))
    })
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search