首页 > 解决方案 > 想不出这个正则表达式的解决方案

问题描述

我有以下字符串列表:

$list = array(
 'c1' => '{sometext...} 1tb hdd 1tb hdd {sometext...}'
 'c2' => '{sometext...} 1tb hdd 1tb {sometext...}',
 'c3' => '{sometext...} hdd 1tb hdd 1tb {sometext...}',
 'c4' => '{sometext...} hdd 1tb hdd 1tb hdd {sometext...}'
);

以及以下应该在所有字符串上运行的正则表达式,如果找到匹配项,则返回,true否则返回false

/(?<!hdd\s)(\dtb hdd \dtb){1,}(?!\shdd)/

截至目前,我的结果集如下所示:

'c1' => false,
'c2' => true,
'c3' => false,
'c4' => false

但是,为了获得正确的结果,将改为标记c4true。我怎样才能改变我的正则表达式,以达到预期的结果?

用例:用例是正确识别产品标题命名中的模棱两可的属性在 case1 和 case3 中,可以很容易地确定哪个容量属于哪个存储设备,但是在其他两种情况下,它是不可编程确定的,因为hdd没有容量值。

注意:计算hdd字符串中实例的数量并不是一个好的解决方案,因为在{sometext...}字符串的一部分中,文本的其他实例可能会出现不同类型的噪音。

标签: phpregex

解决方案


您可以使用

(?<=(hdd\s)|)\dtb hdd \dtb(?(1)(?=\shdd)|(?!\shdd))
(?:hdd\s+\dtb hdd \dtb(?!\s+hdd)|(?<!hdd\s)\dtb hdd \dtb\s+hdd)(*SKIP)(*F)|\dtb hdd \dtb

请参阅正则表达式演示 #1正则表达式演示 #2

细节#1

  • (?<=(hdd\s)|)- 检查当前位置左侧是否有hdd+whitespace(捕获到第 1 组)或空字符串
  • \dtb hdd \dtb- 匹配数字 + tb hdd + 数字 +tb
  • (?(1)(?=\shdd)|(?!\shdd))- 如果第 1 组值不为空,请确保hdd在当前位置的右侧有一个空格,否则,请确保在同一位置找不到此模式。

细节#2

  • (?:hdd\s+\dtb hdd \dtb(?!\s+hdd)|(?<!hdd\s)\dtb hdd \dtb\s+hdd)(*SKIP)(*F)- 匹配hdd\s+\dtb hdd \dtb没有紧跟 1+ 空格 +hdd\dtb hdd \dtb\s+hdd前面没有紧跟hdd+ 空格的模式,使这些匹配失败并继续从失败位置搜索下一个匹配
  • |- 或者
  • \dtb hdd \dtb- 匹配数字, tb hdd , 数字, tb.

查看PHP 演示

$list = array(
 'c1' => '{sometext...} 1tb hdd 1tb hdd {sometext...}',
 'c2' => '{sometext...} 1tb hdd 1tb {sometext...}',
 'c3' => '{sometext...} hdd 1tb hdd 1tb {sometext...}',
 'c4' => '{sometext...} hdd 1tb hdd 1tb hdd {sometext...}'
);
print_r(preg_grep('~(?<=(hdd\s)|)\dtb hdd \dtb(?(1)(?=\shdd)|(?!\shdd))~', $list));
// => Array
//   (
//     [c2] => {sometext...} 1tb hdd 1tb {sometext...}
//     [c4] => {sometext...} hdd 1tb hdd 1tb hdd {sometext...}
//   )

推荐阅读