我使用正则表达式已经有很多年了,编写正则表达式从来没有这么麻烦。我正在使用PHP 7.2.2的preg_match()返回匹配数字的数组以进行解析,因此将正则表达式中的括号删除。
我试图匹配一个或多个数字,后跟一个“ x”,再匹配一个或多个数字,其中整个字符串后不带连字符。当$ input为“ 18x18”或“ 18x18-”时,匹配为18和1。当$ input为“ 8x8”时,没有匹配。我似乎在这里做一些根本错误的事情。
<?php
$input = "18x18";
preg_match("/(\d+)x(\d+)[^-]/", $input, $matches);
调用print_r($ matches)会导致:
Array
(
[0] => 18x18
[1] => 18
[2] => 1
)
这里有括号,因为我正在使用PHP的preg_match返回匹配项数组。我了解何时应避免使用连字符,并且我尝试了两种方法来确定但得到相同的结果。为什么这个不匹配?
答案 0 :(得分:2)
您可以使用
'~(\d+)x(\d++)(?!-)~'
由于前瞻内部的\d
也将禁止部分匹配第二位数字,因此它也可以不带有所有格修饰符而写为'~(\d+)x(\d+)(?![-\d])~'
,因为
或者,除了前行之外,您还可以使用单词边界:
'~\b(\d+)x(\d+)\b(?!-)~'
请参见regex demo #1和regex demo #2。
详细信息
(\d+)x(\d++)(?!-)
/ (\d+)x(\d+)(?![-\d])
-匹配并将1个或多个数字捕获到组1中,然后匹配x
,然后匹配并将一个或多个数字捕获到组2中 ,而不会回溯到数字匹配模式中,并且一次执行(?!-)
否定超前检查(确保在当前位置之后没有-
)一次 \d++
之后匹配所有可以匹配的数字。在\d+(?![-\d])
的情况下,先匹配1+个数字,然后负向查找确保当前位置右边没有数字和 -
。 \b(\d+)x(\d+)\b(?!-)
-首先匹配单词边界,然后将1个或多个数字匹配并捕获到组1中,然后匹配x
,然后将一个或多个数字匹配并捕获到组2中,然后断言有一个单词边界,只有这样才能确保之后没有-
。查看PHP demo:
if (preg_match('~(\d+)x(\d++)(?!-)~', "18x18", $m)) {
echo "18x18: " . $m[1] . " - " . $m[2] . "\n";
}
if (preg_match('~\b(\d+)x(\d+)\b(?!-)~', "18x18", $m)) {
echo "18x18: " . $m[1] . " - " . $m[2] . "\n";
}
if (preg_match('~(\d+)x(\d++)(?!-)~', "18x18-", $m)) {
echo "18x18-: " . $m[1] . " - " . $m[2] . "\n";
}
if (preg_match('~\b(\d+)x(\d+)\b(?!-)~', "18x18-", $m)) {
echo "18x18-: " . $m[1] . " - " . $m[2];
}
输出:
18x18: 18 - 18
18x18: 18 - 18