正则表达式匹配没有其他字符串的特定字符串

Regex match specific string without other string

所以我制作了这个正则表达式:

/(?!for )€([0-9]{0,2}(,)?([0-9]{0,2})?)/

仅匹配以下两个句子中的第一个:

  1. 这些商品可享受 50,20 欧元的折扣
  2. 该商品现价 €30,20

您可能已经注意到,我希望第二句中的金额不要匹配,因为它不是折扣金额。但我不确定如何在正则表达式中找到它,因为我能找到的所有选项如下:

(?!foo|bar)

从我的例子中可以看出,这个选项似乎不能解决我的问题。

示例: https://www.phpliveregex.com/p/y2D

建议?

您可以使用

(?<!\bfor\s)€(\d+(?:,\d+)?)

参见regex demo

详情

  • (?<!\bfor\s) - 如果在当前位置
  • 之前有一个完整的单词 for 和一个空格,则匹配失败的负面回顾
  • - 欧元符号
  • (\d+(?:,\d+)?) - 第 1 组:一个或多个数字后跟可选的逗号序列和一个或多个数字

参见PHP demo

$strs= ["discount of €50,20 on these items","This item on sale now for €30,20"];
foreach ($strs as $s){
    if (preg_match('~(?<!\bfor\s)€(\d+(?:,\d+)?)~', $s, $m)) {
        echo $m[1].PHP_EOL;
    } else {
        echo "No match!";
    }
}

输出:

50,20
No match!

您可以确保匹配行中第一个 discount

\bdiscount\h[^\r\n€]*\K€\d{1,2}(?:,\d{1,2})?\b

说明

  • \bdiscount\h一个字界,匹配打折,至少一个space
  • [^\r\n€]\K 匹配 0+ 次除 € 或换行符之外的任何字符,然后重置匹配缓冲区
  • €\d{1,2}(?:,\d{1,2})? 匹配 €,1-2 位数字,可选部分匹配 , 和 1-2 位数字
  • \b一个单词边界

Regex demo | Php demo

$re = '/\bdiscount\h[^\r\n€]*\K€\d{1,2}(?:,\d{1,2})?\b/';
$str = 'discount of €50,20 on these items €
This item on sale now for €30,20';

if (preg_match($re, $str, $matches)) {
    echo($matches[0]);
}

输出

€50,20