Regex match specific string without other string

Viewed 79

So I've made this regex:

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

to match only the first of the following two sentences:

  1. discount of €50,20 on these items
  2. This item on sale now for €30,20

As you might've noticed already, I'd like the amount in the 2nd sentence not to be matched because it's not the discount amount. But I'm quite unsure how to find this in regex because of all I could find offer options like:

(?!foo|bar)

This option, as can be seen in my example, does not seem to be the solution to my issue.

Example: https://www.phpliveregex.com/p/y2D

Suggestions?

2 Answers

You can use

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

See the regex demo.

Details

  • (?<!\bfor\s) - a negative lookbehind that fails the match if there is a whole word for and a whitespace immediately before the current position
  • - a euro sign
  • (\d+(?:,\d+)?) - Group 1: one or more digits followed with an optional sequence of a comma and one or more digits

See the 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!";
    }
}

Output:

50,20
No match!

You could make sure to match the discount first in the line:

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

Explanation

  • \bdiscount\h A word boundary, match discount and at least a single space
  • [^\r\n€]\K Match 0+ times any char except € or a newline, then reset the match buffer
  • €\d{1,2}(?:,\d{1,2})? Match €, 1-2 digits with an optional part matching , and 1-2 digits
  • \b A word boundary

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]);
}

Output

€50,20
Related