PHP正则表达式检查长度而不使用前瞻

Posted

技术标签:

【中文标题】PHP正则表达式检查长度而不使用前瞻【英文标题】:PHP regex check length without using lookahead 【发布时间】:2021-08-17 19:41:15 【问题描述】:

查看了另外 2 个与正则表达式相关的问题,这两个问题都远远超出了我在 X'D 方面需要的帮助。

<?php 

$userName = trim($_POST['username']);
if(preg_match("/^[a-zA-Z].*(?(\d)).8,$/", $userName))
    
    echo 'woot!';

我不太确定它为什么会失败。我知道它检查第一个字符必须是 alpha,然后去更多 * 但最后检查它是否是一个数字?(\ d)...但是为什么不检查我的 $userName 的长度是否为 8 或更多?

如果我这样做

... *(?(\d)8, 

它会查找 8 位或更多位,而不是字符串本身是否为 8 位或更多位。

用户必须:以字母开头,只能以数字结尾,并且只能包含 alphaNumeric,必须至少为 8 个字符,并且大小写相同。也就是说我需要在我的正则表达式末尾添加一个 i。


因此,没有办法将其转换为正则表达式的形式,向前看? ^...$.8, 不行吗?

【问题讨论】:

请清楚地告诉我们用户名的规则是什么?很明显,它必须以字母开头,并且在稍后的某个时间点也有一个数字。其余的不清楚。 用户必须:以字母开头,只能以数字结尾,并且只能包含字母数字,必须至少为8个字符,并且大小写相同。也就是说我需要在我的正则表达式末尾添加一个 i。 【参考方案1】:

用户必须:以字母开头,只能以数字结尾,并且只能包含 alphaNumeric,必须至少为 8 个字符,并且大小写相同。

你可以使用这个简单的正则表达式来满足这个要求:

^[A-Za-z][a-zA-Z\d]6,\d$

正则表达式详细信息:

^:开始 [A-Za-z]: 匹配开头的 ASCII 字母 [a-zA-Z\d]6,:匹配一个字母或数字 6 次或更多次 \d:匹配结束前的一个数字 $:结束

RegEx Demo

【讨论】:

您可以将其简化为 ^[A-Z][A-Z\d]6,\d$ 并在不区分大小写模式下使用它。 是的,我们可以像这样使用/i。我想我只是想在正则表达式中给出完整的解决方案,只是为了便于阅读,否则 /^[A-Z][A-Z\d]6,\d$/gmi 会更短。 @Coding_Noob:这个解决方案对你有用吗?【参考方案2】:

使用以下正则表达式模式:

^(?=.8,$)[A-Z][A-Z0-9]*[0-9]+$

示例脚本:

$userName = trim($_POST['username']);
if (preg_match("/^(?=.8,$)[A-Z][A-Z0-9]*[0-9]+$/i", $userName)) 
    echo "MATCH";

值得注意的是,正则表达式模式在模式的开头使用(?=.8,$)。这是一个积极的lookahead,它断言匹配至少有 8 个字符。

如果您不想使用前瞻,您可以使用strlen() 明确检查用户名长度:

$userName = trim($_POST['username']);
if (preg_match("/^[A-Z][A-Z0-9]*[0-9]+$/i", $userName) &&
    strlen($userName) >= 8) 
    echo "MATCH";

【讨论】:

是的,我看到了一些关于前瞻的事情;有没有办法做到这一点?我们在我所参加的课程中没有涉及到这一点,我真的很想了解为什么它不能像我的正则表达式那样工作;或者它是如何工作的:)? 使用strlen()查看字符数? 因此没有办法将其转换为正则表达式,然后向前看? ^...$.8, 不起作用? (你可以省略[0-9]+之后的最后一个+作为字符类,然后它也匹配数字)

以上是关于PHP正则表达式检查长度而不使用前瞻的主要内容,如果未能解决你的问题,请参考以下文章

向复杂的正则表达式添加例外(使用前瞻和后瞻)

Javascript:检查正则表达式是不是包含捕获组而不执行它[关闭]

如何在正则表达式中使用前瞻和 $

Prometheus(公制)使用逆正则表达式匹配/负前瞻重新标记配置

负前瞻正则表达式贪婪(为啥.*?太贪婪)

js-正则表达式边界符和前瞻后顾的使用-保证你看明白