我正在尝试将正则表达式约束应用于 Symfony 表单输入。输入的要求是字符串的开头和所有逗号必须后跟零个或多个空格,然后是 a#或@符号,除非它是空字符串。
据我所知,没有办法告诉约束使用preg_match_all而不仅仅是preg_match,但它确实有能力否定匹配。所以,我需要一个preg_match不匹配给定场景的正则表达式:any string containing the start of the string or a comma, followed by zero or more whitespace, followed by any character that is not a # or @ and is not the end of the string,但将匹配其他所有内容。这里有一些例子:
preg_match(..., ''); // No match
preg_match(..., '#yolo'); // No match
preg_match(..., '#yolo, #swag'); // No match
preg_match(..., '#yolo,@swag'); // No match
preg_match(..., '#yolo, @swag,'); // No match
preg_match(..., 'yolo'); // Match
preg_match(..., 'swag,#yolo'); // Match
preg_match(..., '@swag, yolo'); // Match
Run Code Online (Sandbox Code Playgroud)
我本以为肯定/(^|,)\s*[^@#]/会奏效,但是在每种情况下都会出现 1 个或多个空格的情况,这似乎是由于星号造成的。如果我去掉星号,preg_match('/(^|,)\s[^@#]/', '#yolo, @swag')当恰好有一个空格时不匹配(根据需要),但是一旦我重新引入星号,它就会中断任何数量的空格 > 0。
我的理论是正则表达式引擎将第二个空格解释为不在字符集中的字符[@#],但这只是一个理论,我不知道该怎么做。我知道我可以创建一个自定义约束来preg_match_all解决这个问题,但如果可能的话,我想避免这种情况。
您可以使用
'~(?:^|,)\s*+[^#@]~'
Run Code Online (Sandbox Code Playgroud)
在这里,+符号定义了一个*+ 占有量词匹配 0 次或多次出现的空白字符,\s*如果[^@#]不能匹配后续字符,则不允许正则表达式引擎回溯到模式。
请参阅正则表达式演示。
细节
(?:^|,) - 字符串的开头或 ,\s*+- 零个或多个空白字符,所有格匹配(即如果下一个字符与[^#@]模式不匹配,则整个模式匹配将失败)[^@#]- 一个否定字符类匹配任何字符,但@和#。