Jump to content

Regex to update particular pattern in string


ryonn

Recommended Posts

Hi all,

 

I am new to php and regex.

I was told to update the following string:

the [%quick%] brown fox jumps [%over%] the lazy dog [%lorem%] ipsum dolor sit amet

to be

the QUICK brown fox jumps OVER the lazy dog LOREM ipsum dolor sit amet

Basically its just to uppercase the string withing [% %]

 

How can I achieve this?

I have done several experiments, but no avail:

 

Such as this.. not working:

$ret = "the [%quick%] brown fox";


$ret = preg_replace('#\[%(.+)%\]#iUs', strtoupper($1), $ret);
echo $ret;
 

 

 

Please help

Edited by ryonn
Link to comment
Share on other sites

You need to use preg_replace_callback, If you're using PHP5.3 or latter you'll can use an anonymous function as the callback

 

$ret = preg_replace_callback('#\[%(.+)%\]#iUs', 
                                                function($m) {
                                                     return strtoupper($m[1]); // upper case the captured word
                                                }
                            , $ret);

 

otherwise the code will be

function makeUppercase($m) {
	return strtoupper($m[1]);
}
$ret = preg_replace_callback('#\[%(.+)%\]#iUs', 'makeUppercase', $ret);
Link to comment
Share on other sites

Hi Ch0cu3r,

 

Thanks for the reply solution. It works great!

For the

 

function makeUppercase($m) { 
return strtoupper($m[1]);
}
 
Is there a way to make another parameter?
 
Because I want to make it so that:
 
// Not the actual code
$test = "(somewords)";
function makeUppercase($m) { 
return strtoupper($m[1] . $test);
}

@Josh:

You're right.

i am not really sure about what the letters are about.

I tried removing one by one, everything still seems to work fine:

$ret = preg_replace_callback('#\[%(.+?)%\]#', 'makeUppercase', $ret);
What do you think?
 
Edited by ryonn
Link to comment
Share on other sites

i am not really sure about what the letters are about.

I tried removing one by one, everything still seems to work fine:

They are called modifiers.

 

By default, + is a greedy quantifier, meaning it will match everything it can possibly match, and then only give up what it consumes to satisfy the rest of the pattern.

 

So let's say you have this string:

the [%quick%] brown fox jumps [%over%] the lazy dog [%lorem%] ipsum dolor sit amet

And you have this pattern: #\[%(.+)%\]#

 

So what happens is first the [%] in front of "quick" is matched. Then (.+) is going to match all the way to the end of the string. Then for the engine to match the closing %], the + starts backtracking from the end of the sting, giving up characters until it reaches the first %] it finds. So, instead of matching for 3 of those [%word%] things, you end up with one match looking like this:

 

[%quick%] brown fox jumps [%over%] the lazy dog [%lorem%]

 

That is where the U modifier comes in. The U modifier inverses quantifiers. It makes greedy quantifiers to be non-greedy. What that means is instead of matching everything it can and then backtracking, it moves forward one char at a time until the rest of the pattern is matched. So this achieves the desired match you want: that is, to only match until the next %] instead of the very last occurrence. So what you had wasn't wrong, per se. But there is another way to make quantifiers lazy: by putting a ? after them. This is what most people recognize, and what virtually every regex engine recognizes. Whereas most people barely even know regex, let alone the U modifier, and that modifier isn't available in a lot of other languages, which would make it harder for you to translate your regex to another language if it comes up.

 

IOW using the U modifier is akin to speaking in double negatives.. you're technically right, but you're more often than not just going to confuse people.

 

 

The i modifier is to make the regex case-insensitive. This isn't necessary in your pattern because you don't have any letters in it.

 

The s modifier makes the dot (.) also match newline characters (by default, it does not). Again, unless you plan on having newline characters in between your [%..%] tags, this isn't necessary.

 

 

For the

function makeUppercase($m) { 
return strtoupper($m[1]);
}
 

Is there a way to make another parameter?

 

Because I want to make it so that:

 

// Not the actual code
$test = "(somewords)";
function makeUppercase($m) { 
return strtoupper($m[1] . $test);
}

 

If you have php5.3+ then you can do it like this:

 

$ret = 'the [%quick%] brown fox jumps [%over%] the lazy dog [%lorem%] ipsum dolor sit amet';

$test='foobar';
$ret = preg_replace_callback(
  '#\[%(.+?)%\]#', 
  function($m) use ($test) {
    return strtoupper($m[1].$test); // upper case the captured word
  },
  $ret);
echo $ret;
If you are NOT on php version 5.3+, then upgrade! Seriously.. but if that's not an option at this time, then it's not (directly) possible. The workaround is to declare the variable as globally scoped. In general, this is a bad idea, as it defeats the purpose of functions having scope. But this is one of the grudgingly acceptable use cases for global variables, since there isn't really an alternative for older versions of php (seriously, at least upgrade to php 5.3). Here is how it would look:

 

function makeUppercase($m) {
  global $test;
	return strtoupper($m[1].$test);
}
$ret = 'the [%quick%] brown fox jumps [%over%] the lazy dog [%lorem%] ipsum dolor sit amet';
$test='foobar';
$ret = preg_replace_callback('#\[%(.+?)%\]#', 'makeUppercase', $ret);

echo $ret;
Link to comment
Share on other sites

Hi josh,

 

Thank you for the explanation about the modifiers.

New things to learn everyday =)
 

About the 'use', it is something new for me.

I have checked the phpinfo in my server, it is 5.3.26

but it gives error:

Parse error: syntax error, unexpected T_USE, expecting '{' in filename yada yada

Here is my code:

function makeUppercase($m) use ($test) {
    return strtoupper($m[1].$test);
}
$ret = 'the [%quick%] brown fox jumps [%over%] the lazy dog [%lorem%] ipsum dolor sit amet';
$test='foobar';
$ret = preg_replace_callback('#\[%(.+?)%\]#', 'makeUppercase', $ret);

echo $ret;

I guess 'use' can only be used for the 'inline' function right?

 

I try to avoid using global since it seems not nice for me, but at this point I think there is no other option  :-\

Edited by ryonn
Link to comment
Share on other sites

use ($test) can only be used with anonymous functions. If you're not going to use anonymous functions then you'll need to use .josh's second code example, which was

function makeUppercase($m) {
  global $test;
	return strtoupper($m[1].$test);
}
$ret = 'the [%quick%] brown fox jumps [%over%] the lazy dog [%lorem%] ipsum dolor sit amet';
$test='foobar';
$ret = preg_replace_callback('#\[%(.+?)%\]#', 'makeUppercase', $ret);

echo $ret;
Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.