-1

I'm trying to find a regular expression for unlimited digits but limited underscores.

So let's say max_underscore = 3.

Then

123_456_678 is ok (3 underscores)
1234213_2132135678 is ok (2 underscores)

But

13_4156_7_012_1 is not ok (4 underscores)

Toto
  • 89,455
  • 62
  • 89
  • 125
michael
  • 308
  • 3
  • 18

2 Answers2

2

If underscore is not allowed at the begining or at the end and it is not allowed to have 2 or more consecutive underscore:

^(?:\d+_?){3}\d+$

If underscore is allowed at the begining or at the end:

^(?:\d*_?){3}\d*$

These regex match string that have 0 upto 3 underscore but not more.

See these 2 regexes in action:

$strings = array(
'123456',
'1_2_3_456',
'123_456',
'_123_456_',
'1_2_3_4_5_6',
'123___456',
);
$num = 3;
echo 'using "^(?:\d+_?){3}\d+$"',"\n";
foreach($strings as $string) {
    if (preg_match("/^(?:\d+_?){".$num."}\d+$/", $string)) {
        echo "OK: $string\n";
    } else {
        echo "KO: $string\n";
    }
}
echo 'using "^(?:\d*_?){3}\d*$"',"\n";

foreach($strings as $string) {
    if (preg_match("/^(?:\d*_?){".$num."}\d*$/", $string)) {
        echo "OK: $string\n";
    } else {
        echo "KO: $string\n";
    }
}

Output:

using "^(?:\d+_?){3}\d+$"
OK: 123456
OK: 1_2_3_456
OK: 123_456
KO: _123_456_
KO: 1_2_3_4_5_6
KO: 123___456
using "^(?:\d*_?){3}\d*$"
OK: 123456
OK: 1_2_3_456
OK: 123_456
OK: _123_456_
KO: 1_2_3_4_5_6
OK: 123___456
Toto
  • 89,455
  • 62
  • 89
  • 125
1

If you can, represent each of the other characters.

For example with 3 underscores :

\d*_\d*_\d*_\d*

If you want to match 3 or less underscores, you can make parts of the regex optional :

\d*(_\d*(_\d*(_\d*)?)?)?

Note that this allow two consecutive underscores and underscores at the start and end of the string, which you could avoid by using + instead of * :

\d+_\d+_\d+_\d+
Aaron
  • 24,009
  • 2
  • 33
  • 57