我有以下字符串:
SEDCVBNT S800BG09 7GFHFGD6H 324235346 RHGF7U S8-00BG/09 7687678
和以下正则表达式:
preg_match_all('/\b(?=.+[0-9])(?=.+[A-Z])[A-Z0-9-\/]{4,20}/i', $string, $matches)
我想要实现的是返回所有“单词”:
不幸的是,上面的正则表达式返回:
Array ( [0] => Array ( [0] => SEDCVBNT [1] => S800BG09 [2] => 7GFHFGD6H [3] => 324235346 [4] => RHGF7U [5] => S8-00BG/09 ) )
我不想返回“SEDCVBNT”或“324235346”。
我到处搜索,对上面的正则表达式尝试了很多小改动,但我完全坚持这一点。我真的很感激任何帮助。
提前致谢。
你需要稍微高级的正则表达式语法。
我想出的正则表达式是
(?<=\s|^)(?=[\w/-]*\d[\w/-]*)(?=[\w/-]*[A-Za-z][\w/-]*)([\w/-])+(?=\s|$)
让我们解释一下:
[\w/-]
出现了很多;这意味着“任何单词字符(包括字母、数字、重音字母等)或斜线或破折号”——实际上,您认为是有效标记一部分的所有字符。(?=[\w/-]*\d[\w/-]*)
.(?=\s|$)
)和负(开头:(?<=\s|^)
)前瞻以确保仅当整个文本标记在空白字符之后开始时才进行匹配或在输入字符串的开头 (\s|^
) and 后跟一个空白字符或终止输入字符串 (\s|$
).
([\w/-])+
相同,实际上我使用它们来匹配匹配多个模式的文本:两个先行和捕获组模式在结束
\d
)。
A-Za-z
)。
/
和
-
.
/
和
-
(捕获组)。
注意: refiddle.com 似乎不能很好地处理负面回顾,因此链接后的正则表达式不包括初始(?<=\s|^)
部分。这意味着它会错误地匹配
DEF456
中的
ABC123$DEF456
。
\b(?=\S*?\d)(?=\S*?[a-z])\S+?(?=$|\s)
preg_match_all('/\b(?=\S*?\d)(?=\S*?[a-z])\S+?(?=$|\s)/i', $string, $matches)
\b
) 不能依赖于识别此任务的“单词”的边缘,因为例如,以斜线结尾后跟空格的单词不满足单词边界。单词边界仅在确定
\w
和
\W
之间的零宽度位置(反之亦然)时才适用。代码:(
演示)
$string = 'SEDCVBNT S800BG09 7GFHFGD6H 324235346 RHGF7U S8-00BG/09 7687678';
preg_match_all(
'~
(?:^|\s) #match start of string or whitespace
\K #release previously matched characters
(?=\S*[a-z]) #lookahead for zero or more visible characters followed by letter
(?=\S*\d) #lookahead for zero or more visible characters followed by number
[a-z\d/-]+ #match one or more consecutive whitelisted characters
(?=\s|$) #lookahead for a whitespace or the end of string
~xi', #ignore literal whitespaces in pattern, use case-insensitivity with letters
$string,
$m
);
var_export($m);