Checking min no of characters in capturing group in Regex

Viewed 121

I have a question in regex

I am dealing with numbers 0 and 1 only

I have 10 digit number grouped into 4 as below

([01]{2})([01]{4})([01]{2})([01]{2})

I need to match all those numbers with min 2 1's in the second group which is ([01]{4}) , no matter how many 0's or 1's other groups are having. I am interested only in the second group

For example, these are the potential matches are

0000110000
0011000000
0001100000
0000110000

I tried using positive look ahead like :

^(\d{2})((?=\d*1{2,}\d*)(\d{4}))(\d{2})(\d{2})

but this is matching even

0000000011

Any help is deeply appreciated

4 Answers

If the ones need to be consecutive (as per your sample data), maybe you can use:

^(?=[01]{2,4}11)[01]{10}$

See the online demo. The idea here is that you would match 2-4 zero's or 1's upto a sequence of two ones. It makes sense if you realise the only combinations that are allowed would have the minimum of two 1's ("11") sequence after exactly 2-4 other digits.

  • ^ - Start line anchor.
  • (?=[01]{2,4}11) - Open positive lookahead to look for 2-4 characters from our characters class upto "11".
  • [01]{10} - Match exactly 10 characters from our character class.
  • $ - End line anchor.

If need be you can change the [01]{10} pieces where you'd use capture groups.


EDIT:

If they don't have to be consecutive, maybe you can work with:

^[01]{2}(?=[01]{8}$)([01]{0,2}1[01]{0,2}1[01]{0,2})[01]{4}$

See the online demo.

Or less verbose:

^(?=[01]{10}$)(..)(.*1.*1.*)(..)(..)$

See the demo

If the two 1s are not necessarily consecutive in Group 2, you can use

^([01]{2})(?=(?:[01]*1){2}[01]{4,6}$)([01]{4})([01]{2})([01]{2})$

See the regex demo

Details:

  • ^ - start of string
  • ([01]{2}) - Group 1: two occurrences of 1 or 0
  • (?=(?:[01]*1){2}[01]{4,6}$) - immediately to the right of the current location, there must be two occurrences of any zero or more 0 or 1 chars followed with 1 and then there must be four, five or six 1 or 0 chars till the end of string
  • ([01]{4}) - Group 2: four occurrences of 1 or 0
  • ([01]{2}) - Group 3: two occurrences of 1 or 0
  • ([01]{2}) - Group 4: two occurrences of 1 or 0
  • $ - end of string.

Not a job for regex but for bitwise operators:

(in PHP):

$nums = [
    '0000110000',
    '0011000000',
    '0001100000',
    '1000110000',
    '0000000110',
    '0001000000'
];

foreach ($nums as $num) {
    if ( !in_array((bindec($num) >> 4) & 15, [0, 1, 2, 4, 8]) )
        echo $num, PHP_EOL;
}

You can probably do that in any language.

If a positive lookahead is supported, you could also assert that group 2 has as least 11 using a positive lookahead.

^([01]{2})(?=[01]{0,2}11)([01]{4})([01]{2})([01]{2})$
  • ^ Start of string
  • ([01]{2}) - Group 1: two occurrences of 1 or 0
  • (?= Positive lookahead
    • [01]{0,2}11 Match 0-2 times either 0 or 1 and match 11
  • ) Close lookahead
  • ([01]{4}) - Group 2: four occurrences of 1 or 0
  • ([01]{2}) - Group 3: two occurrences of 1 or 0
  • ([01]{2}) - Group 4: two occurrences of 1 or 0
  • $ - end of string.

Regex demo

Or you can write out all 3 alternatives matching 11

^([01]{2})(11[01][01]|[01]11[01]|[01][01]11)([01]{2})([01]{2})$

Regex demo

Related