提取符合特定条件的“单词”

问题描述 投票:0回答:3

我有以下字符串:

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 个数字
  • 包含至少 1 个字母
  • 可能包含'/'
  • 可能包含'-'

不幸的是,上面的正则表达式返回:

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

我不想返回“SEDCVBNT”或“324235346”。

我到处搜索,对上面的正则表达式尝试了很多小改动,但我完全坚持这一点。我真的很感激任何帮助。

提前致谢。

php regex preg-match-all
3个回答
2
投票

你需要稍微高级的正则表达式语法。

我想出的正则表达式是

(?<=\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
    )。
  • 捕获组匹配一个或多个单词字符和/或
  • /
    -
    .
因此,要匹配捕获组,被检查的文本必须:

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

注意: refiddle.com 似乎不能很好地处理负面回顾,因此链接后的正则表达式不包括初始(?<=\s|^)

部分。这意味着它会错误地匹配
DEF456
中的
ABC123$DEF456


0
投票
这是原始正则表达式:

\b(?=\S*?\d)(?=\S*?[a-z])\S+?(?=$|\s)



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

0
投票
单词边界标记 (

\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);
    
© www.soinside.com 2019 - 2024. All rights reserved.