匹配至少包含 1 个字母和 1 个数字且可能包含斜杠和连字符的所有空格分隔"words"



我有以下字符串:

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)

我试图实现的是;单词";即:

  • 至少包含1个数字
  • 至少包含一个字母
  • 可能包含/
  • 可能包含-

不幸的是,上面的正则表达式也返回纯字母和纯数字单词:

Array (
  [0] => Array (
      [0] => SEDCVBNT
      [1] => S800BG09
      [2] => 7GFHFGD6H
      [3] => 324235346
      [4] => RHGF7U
      [5] => S8-00BG/09
  )
) 

我不希望返回SEDCVBNT324235346

您需要稍微高级一点的regex语法。

我想到的正则表达式是

(?<=s|^)(?=[w/-]*d[w/-]*)(?=[w/-]*[A-Za-z][w/-]*)([w/-])+(?=s|$)

让我们来解释一下:

  • 语法[w/-]出现了很多;这意味着";任何单词字符(包括字母、数字、重音字母等)或斜线或短划线"——实际上,您认为是有效令牌一部分的所有字符
  • 正则表达式使用正向前瞻来确保在尝试匹配的地方,以下文本确实满足某些条件。正面展望如下:(?=[w/-]*d[w/-]*)
  • 它还使用正数(末尾的一个:(?=s|$)负数(开头的:(?<=s|^))前瞻,以确保只有当整个文本标记开始于空白字符之后或位于输入字符串(s|^的开头并带有空白字符或终止输入字符串(s|$)时,才进行匹配
  • 由于两个内部先行模式几乎与捕获组模式([w/-])+相同,因此实际上我使用它们只匹配与多个模式匹配的文本:先行模式和都是末尾的捕获组模式
  • 第一前瞻确保下一个令牌包括至少一个数字(d
  • 第二前瞻确保下一个令牌包括至少一个字母(A-Za-z
  • 捕获组匹配一个或多个单词字符和/或CCD_ 14和CCD_

因此,为了使捕获组匹配,被检查的文本必须:

  1. 前面是空白或输入字符串的开头(这样可以防止部分单词匹配从不允许的字符后面开始)
  2. 在下一段允许的字符中至少包含一个数字(第一个正向前瞻)
  3. 在下一段允许的字符中至少包含一个字母(第二个正向前瞻)
  4. 仅由单词字符/-(捕获组)组成
  5. 后跟空白或输入字符串的末尾(这样可以防止部分单词匹配以不允许的字符结尾)

这正是您所需要的。:)

注意:refidle.com似乎不能很好地处理负查找,因此链接后的regexp不包括初始(?<=s|^)部分。这意味着它将错误地匹配ABC123$DEF456中的DEF456

不能依赖单词边界标记(b)来识别";单词";对于这个任务,因为例如,以斜杠后跟空格结尾的单词将不满足单词边界。只有当确定wW之间的零宽度位置时,字边界才是合适的(反之亦然)。

代码:(演示)

$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-zd/-]+    #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);

这是原始正则表达式:b(?=S*?d)(?=S*?[a-z])S+?(?=$|s)

preg_match_all('/b(?=S*?d)(?=S*?[a-z])S+?(?=$|s)/i', $string, $matches) 

相关内容

  • 没有找到相关文章

最新更新