ryonn Posted March 22, 2014 Share Posted March 22, 2014 (edited) 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 March 22, 2014 by ryonn Quote Link to comment https://forums.phpfreaks.com/topic/287175-regex-to-update-particular-pattern-in-string/ Share on other sites More sharing options...
Ch0cu3r Posted March 22, 2014 Share Posted March 22, 2014 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); Quote Link to comment https://forums.phpfreaks.com/topic/287175-regex-to-update-particular-pattern-in-string/#findComment-1473532 Share on other sites More sharing options...
.josh Posted March 22, 2014 Share Posted March 22, 2014 Also, and this is just a suggestion.. you should change (.+) to (.+?) and remove the U modifier, since a) the pattern's intention is more readily clear, b) the regex is more portable to other languages. Quote Link to comment https://forums.phpfreaks.com/topic/287175-regex-to-update-particular-pattern-in-string/#findComment-1473565 Share on other sites More sharing options...
ryonn Posted March 22, 2014 Author Share Posted March 22, 2014 (edited) 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 March 22, 2014 by ryonn Quote Link to comment https://forums.phpfreaks.com/topic/287175-regex-to-update-particular-pattern-in-string/#findComment-1473568 Share on other sites More sharing options...
.josh Posted March 23, 2014 Share Posted March 23, 2014 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; Quote Link to comment https://forums.phpfreaks.com/topic/287175-regex-to-update-particular-pattern-in-string/#findComment-1473575 Share on other sites More sharing options...
ryonn Posted March 23, 2014 Author Share Posted March 23, 2014 (edited) 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 March 23, 2014 by ryonn Quote Link to comment https://forums.phpfreaks.com/topic/287175-regex-to-update-particular-pattern-in-string/#findComment-1473580 Share on other sites More sharing options...
Ch0cu3r Posted March 23, 2014 Share Posted March 23, 2014 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; Quote Link to comment https://forums.phpfreaks.com/topic/287175-regex-to-update-particular-pattern-in-string/#findComment-1473598 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.