Php正则表达式验证输入的多次出现

What's the regex for validating input for this

Below 3 line are valid

PROJ9450
PROJ9400-PROJ9401-PROJ9402 ..... PROJ{n}
PROJ9400_1-PROJ9400_2-PROJ9401_1-PROJ9402_1-PROJ9408 ... PROJ{n}_{n}

Below lines are Invalid strings

PROJ450
PRO1223
PROJ9400a-PROJ9401-PROJ9400-PROJ1929-1-PROJ1929
PROJ9400_1-PROJ9400_2-PROJ9401_1-PROJ9402_1-PROJs453 ... PROJ{n}_{n}

I tried this

if( preg_match('/(PROJ)[0-9]{4}(-|_)?[0-9]+)/', $input) )
{

}

I can split and can validate like something like below , but I want to do this by single regex

 foreach(explode('-',$input) as $e)
 {
        if( !preg_match('/(PROJ)[0-9]{4}(-|_)?[0-9]+)/', $e) )
        {
             return 'Invalid Input';
        }
 }

Input can be just prefixed by PROJ and 4 digit number

PROJ9450

OR

Input can be prefixed by PROJ and 4 digit number - prefixed by PROJ and 4 digit number like this upto n

PROJ9400-PROJ9401-PROJ9402 ..... PROJ{n}

OR

Input can be prefixed by PROJ and 4 digit number undescore digit - prefixed by PROJ and 4 digit number underscore digit like this upto n

PROJ9400_1-PROJ9400_2-PROJ9401_1-PROJ9402_1 ... PROJ{n}_{n}

You need to match the block starting with PROJ and followed with 4 digits (that are optionally followed with - or _ and 1+ digits) repeatedly.

Use

/^(PROJ[0-9]{4}(?:[-_][0-9]+)?)(?:-(?1))*$/

See the regex demo

Details:

  • ^ - start of string anchor
  • (PROJ[0-9]{4}(?:[-_][0-9]+)?) - Group 1 (that will be later recursed with (?1) recursion construct) capturing:
    • PROJ - a literal char sequence
    • [0-9]{4} - 4 digits
    • (?:[-_][0-9]+)? - an optional (1 or 0 occurrences) of
  • (?:-(?1))* - zero or more occurrences of - followed with Group 1 subpattern up to...
  • $ - end of string (better replace it with \z anchor that matches the very end of the string).