以该字符开头和结尾的字符串不应该是匹配的。
这样做是不是最简单:
$string = '!test';
preg_match('/^(!?)([a-z0-9]{1,10})(!?)$/i', $string, $matches);
和检查$匹配?
如果在开头或结尾只有一个字符,只需这样说:
/^!|!$/
不需要捕获组
更新:为了确保你得到一个感叹号和十个字母或十个字母和一个感叹号,像这样构建你的模式:
/^!?[a-z0-9]{1,10}$|^[a-z0-9]{1,10}!?$/
它看起来像在重复自己,但实际上比三个捕获组更便宜和更快。
我在regex101中为此组合了一个单元测试。