【问题标题】:Regex match numbers not followed by a hyphen正则表达式匹配数字后不带连字符
【发布时间】:2021-09-30 03:11:29
【问题描述】:

我使用正则表达式已经很多年了,在编写正则表达式时从来没有遇到过这么大的麻烦。我正在使用 PHP 7.2.2 的 preg_match() 返回一个匹配数字的数组以进行解析,因此正则表达式中的括号。

我正在尝试匹配一个或多个数字,后跟一个x,后跟一个或多个数字,其中整个字符串后面没有连字符。当 $input 为 18x1818x18-18x18size 时,匹配项为 181。当$input8x8 时,没有匹配项。

我似乎在这里做一些根本错误的事情。

<?php
$input = "18x18";    
preg_match("/(\d+)x(\d+)[^-]/", $input, $matches);

调用print_r($matches) 会导致:

Array
(
    [0] => 18x18
    [1] => 18
    [2] => 1
)

括号在那里是因为我使用 PHP 的 preg_match 来返回匹配数组。我知道什么时候应该转义连字符,我已经尝试了两种方法来确定,但得到了相同的结果。为什么不匹配?

【问题讨论】:

  • 你想像'~(\d+)x(\d++)(?!-)~'一样吗?
  • PCRE 正则表达式不应与不支持所有格量​​词的 Python re 混淆,因此它不能作为 Negative lookahead not working after character range with plus quantifier 重复关闭。
  • 这个问题不是关于所有格量词的使用。它是关于匹配不跟随字符的东西。如selected answer 中所示,单词边界解决方案对于pythonphp 来说是足够的。
  • 不,这并不总是足够的。字边界根本不是一个解决方案,它是一个workaround(\d+)x(\d+)\b(?!-)won't match12x24size中的大小,而(\d+)x(\d++)(?!-)will
  • 12x24size 不是 OP 要求的一部分。要求应该来自 OP 而不是来自发布的答案。

标签: php regex


【解决方案1】:

你可以使用

'~(\d+)x(\d++)(?!-)~'

它也可以不使用所有格量词写成'~(\d+)x(\d+)(?![-\d])~',因为前瞻内的\d 也将禁止部分匹配第二个数字块。

或者,除了前瞻之外,您还可以使用单词边界:

'~\b(\d+)x(\d+)\b(?!-)~'

请参阅regex demo #1regex 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

【讨论】:

  • 此外,有关所有格量词的更多信息,请参阅Greedy vs. Reluctant vs. Possessive Quantifiers(我把它留在这里,因为我自己也很困惑)
  • @Zenoo 我添加了一个不使用所有格量词的等效模式。
  • 我很惊讶这竟然如此复杂,但它工作得很好。如此简单的事情应该更容易完成。我以前从未使用过所有格量词或单词边界。我需要研究以了解它们的用途。谢谢!
  • 亲爱的 Wiktor,请问\d++\d+ 这里有什么区别?或一般情况下。
  • @AnoushiravanR \d++ 使用所有格量词进行修改,禁止回溯到模式中(=一旦第一次匹配一个或多个数字,就不允许重新匹配输入字符串,正则表达式索引无法通过此匹配文本返回)。因此,在\d++(?!x) 中,在所有数字都匹配后执行一次否定前瞻,如果没有x,则整个匹配失败,不返回匹配。对于\d+(?!x),允许回溯到\d+,如果x后面有两位或多位数字,则最后一位将被截断,然后匹配。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-31
  • 1970-01-01
相关资源
最近更新 更多