Php nonsmooth regex problem

demo:

$str = 'bcs >Hello >If see below!';
$repstr = preg_replace('/>[A-Z0-9].*?see below[^,\.<]*/','',$str);
echo $repstr;

      

I want this tiny program to output "bcs> Hello", but actually it is only "bcs"

What's wrong with my template?

0


a source to share


3 answers


I think the problem is that you are misinterpreting how the non-greedy quantifier works. Once it works, yes, it stops earlier than it otherwise does. But it is not what comes before him (or perhaps the text that comes later). It only concerns the current position. Hence the regex you posted will match all:

">Hello >If see below!"

      

Let's see how it works:

/>[A-Z0-9].*?see below[^,\.<]*/

      

The regex first looks for ">" in "bcs> Hello> If see below!" and finds the first one that is one of them before "Hello". Ok, let's check the next part of the expression:

[A-Z0-9]

      



The next char is H, which matches the pattern [A-Z0-9]. Still good! Further:

.*?

      

We now match all non-newline characters until we get to the first instance to match the rest of the "see below [^ ,. <] *" expressions. If we were to use a simple greedy quantifier, we could match multiple cases of "see below [^ ,. <] *" until we compare the last possible one. (So, if your line went on and there was other text that matched this pattern, it would capture that as well). An unwanted quantifier does not mean that your entire pattern will return the smallest possible match of all possible matches to a string. It simply dictates how the functions of a particular symbol match.

You might want to try the following pattern:

/>[A-Z0-9][^>]*?see below[^,\.<]*/

      

Hope this clears it up!

+4


a source


Why don't you write it like this:



$str = 'bcs >Hello >If see below!';
$repstr = preg_replace('/>If see below[^,\.<]*/','',$str);
echo $repstr;

      

0


a source


This can be a good alternative to what you have. The problem with your regex is that instead of choosing what you want, you choose what you don't want and replace it with an empty string. The best approach in my opinion is to choose what you want, this is what the code below does. What you end up with is what matches the first subproblem, otherwise you will get your string back.

$str = 'bcs >Hello >If see below!';
$repstr = preg_replace('/^([\w]+ >[\w]+).*?see below.*?$/i', '$1', $str);
var_dump($repstr);

      

Hope this helps.

0


a source







All Articles