使用preg_match_all在字符串中查找日期格式,但循环不正确



我试图搜索一个字符串,看看它是否包含一个或多个mm/dd/yy格式的日期。字符串将始终包含一个以日期开头的句子。字符串中可能有多个日期,如果发生这种情况,我需要将其拆分为一个数组。

下面是一个包含多个日期的字符串示例:

12/11/19客户安装的项目。。。。pif cmpt12/27/19客户不满意。客户想要新博士…149.95报价。。。。ncsc cmpt12/29/20 e/c地板pif cmpt

这是我的PHP代码:

$string = "12/11/19 d/c 1item-customer installed.... pif cmpt12/27/19 e/c cust unhappy. cust wants new dr...149.95 quoted....ncsc cmpt12/29/20 e/c floor pif cmpt";
$regex = "/d{2}/d{2}/d{2}/";
preg_match_all($regex, $string, $matches);
$matchCount = count($matches[0]);
$lessmatch = $matchCount - 1;
echo "count is " . $matchCount . "rn";
for ($i = 0; $i <= $lessmatch; $i++) {

$beginpos[$i] = strval(strpos($string,$matches[0][$i]));
$next = $i + 1;
// Check if last match in string
if($i < $lessmatch) {
$endpos = strval(strpos($string,$matches[0][$next]));
$strbetween[$i] = substr($string,$beginpos[$i],$endpos);
}
if($i == $lessmatch) {
$strbetween[$i] = substr($string,$beginpos[$i]);
}

echo $strbetween[$i] . "<br>";
}

我在echo中放入br标记,这样我就可以知道循环下一次移动的时间,这样我就能知道preg_match_all是否正确地检测到了日期模式,我还回显了$matchCount变量,以确保脚本正确地捕捉到了所有出现的情况。它正确地将3作为计数回声,但在打印东西时出错了。这是我得到的:

计数为319年12月11日客户安装的项目。。。。pif cmpt
12/27/19客户不满意。客户想要新博士…149.95报价。。。。ncsc cmpt12/29/20 e/c地板pif cmpt
29/29/20 e/c地板pif cmpt

我不明白为什么它正确地显示了第一个和最后一个项目,但在第二个项目上,它也显示了第三个。。。然后再次显示第三个。我猜这就是我循环的方式,但我似乎不知道如何正确地进行。有人能帮忙吗?

实际错误是,当您调用substr()时,第三个参数是文本的长度,而不是结束位置。这意味着你要求的角色比你需要的要多。

还有一种可能性是,如果同一日期出现两次,此代码将无法正确拆分。您可以使用PREG_OFFSET_CAPTURE,它将为您提供匹配字符串在字符串中的位置,并使用这些值来计算开始和结束(使用substr()时加上减去两者(。。。

$regex = "/d{2}/d{2}/d{2}/";
preg_match_all($regex, $string, $matches, PREG_OFFSET_CAPTURE);
$matchCount = count($matches[0]);
echo "count is " . $matchCount . "rn";
for ($i = 0; $i < $matchCount; $i++) {
$beginpos = $matches[0][$i][1];
$endpos = $matches[0][$i+1][1] ?? strlen($string);
$strbetween[$i] = substr($string, $beginpos, $endpos - $beginpos);
echo $beginpos."->".$endpos."=".$strbetween[$i] . "<br>".PHP_EOL;
}

您可以使用

$string = "12/11/19 d/c 1item-customer installed.... pif cmpt12/27/19 e/c cust unhappy. cust wants new dr...149.95 quoted....ncsc cmpt12/29/20 e/c floor pif cmpt";
print_r(preg_split("/(?!A)(?=(?<!d)d{2}/d{2}/d{2}(?!d))/", $string, 0, PREG_SPLIT_NO_EMPTY));

请参阅PHP演示。输出:

Array
(
[0] => 12/11/19 d/c 1item-customer installed.... pif cmpt
[1] => 12/27/19 e/c cust unhappy. cust wants new dr...149.95 quoted....ncsc cmpt
[2] => 12/29/20 e/c floor pif cmpt
)

图案与匹配

  • (?!A)-不在字符串的开头
  • (?=(?<!d)d{2}/d{2}/d{2}(?!d))-紧挨着右边,必须有两位数字,/,两位,/,两位而不是包含在任何其他数字中

最新更新