2

我需要匹配其中包含@#和任何数字的文本。只要字符在文本中,它们就可以处于随机位置。鉴于此输入:

abc@#d9
a9b#c@d
@@abc#9
abc9d@@
a#b#c@d

正则表达式应匹配前 3 行。目前我的正则表达式是:

/@.*?#.*?[0-9]/

这不起作用,因为它只会按顺序匹配三个字符。如何以随机顺序匹配三个字符?

4

3 回答 3

4

找到一个丑陋的正则表达式,如果你真的必须使用一个:

/(?=.*@)(?=.*#)(?=.*[0-9]).*/

http://jsfiddle.net/BP53f/2/

正则表达式基本上是使用他们所说的lookahead

http://www.regular-expressions.info/lookaround.html

上面链接中的一个简单案例是尝试匹配q,然后是u,通过做q(?=u),这就是为什么它被称为lookahead,它发现q后面是u前面。

让我们以您的有效案例之一为例:a9b#c@d

第一个前瞻是(?=.*@),它指出:匹配任何内容,然后是@。确实如此,即字符串a9b#c,然后由于必须丢弃来自前瞻的匹配,引擎将退回到字符串的开头,即a. 然后它转到

(?=.*#),其中指出:匹配后面的任何内容#,然后在 处找到它a9b。等等。使用前瞻和后退的区别(a)(b)(c)基本上是后退。

从上面的链接:

让我们再看一下内部,以确保您了解前瞻的含义。让我们应用 q(?=u)i 退出。我已将前瞻设为正面,并在其后放置了一个标记。同样,q 匹配 q,u 匹配 u。同样,来自前瞻的匹配必须被丢弃,因此引擎从字符串中的 i 退回到 u。前瞻成功,因此引擎继续执行 i。但我无法匹配你。所以这个匹配尝试失败了。所有剩余的尝试也将失败,因为字符串中没有更多的 q。

它很难看,因为它很难维护......括号内基本上有 3 个不同的子正则表达式。

于 2012-05-31T05:59:09.837 回答
0

使用单独的表达式来确保 @ 和 # 存在。一旦它们是,将它们删除并匹配其余的字符/数字。

于 2012-05-31T05:55:30.877 回答
0

决定我最好把这个写成答案:

$text = "a9b#c@d";
$themAll = "#@";
$themAny = "0123456789";
echo (strspn($themAll, $text)==strlen($themAll) && strpbrk($text, $themAny));

对于维护和一些(有限的)扩展,这应该尽可能容易,尤其是$themAll列表较长时。

于 2012-05-31T08:04:19.803 回答