dwayn Posted January 22, 2011 Share Posted January 22, 2011 Hi all, I am working on a project that require finding links (of format "localhost/view.php?s={some_integer1}&a={some_integer2}" and than finding some_integer1 and some_integer2 in each link found in above string. And finally, some computation is done on basis of value of these some_integers1 and 2 and array $replacement is made ready and finally preg_replace() is caleed... The problem is i am not getting anything as output... Code: <?php $message = "hen an unknown printer took a galley of type and localhost/view.php?s=324&a=2433 scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic localhost/view.php?s=33&a=222 typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing"; $regexExpr = "localhost/view.php?s=[0-9]+&a=[0-9]+" ; preg_match_all($regexExpr, $message, $matches, PREG_PATTERN_ORDER); // some computation done on basis of values stored in $matches[0] array $regexExpr = "[0-9]+"; $i=0; foreach ($matches[0] as $key => $value ) { preg_match_all($regexExpr, $value, $forum, PREG_PATTERN_ORDER); // some computation done and $replacement array get some values here.($forum[0] array and variable $i are used in that computation). } $regexExpr = "localhost/view.php?s=[0-9]+&a=[0-9]+" ; $message = preg_replace($regexExpr, $replacement, $message); echo "$message" ; ?> Output=Nothing .. What could be the problem? Any idea... Is regex used correct? Or maybe i have used variables which are not defined earlier(but than php assume it by itself.isn't it?) Quote Link to comment Share on other sites More sharing options...
.josh Posted January 22, 2011 Share Posted January 22, 2011 You need to escape the ? as it has special meaning in regex. \? instead of ? Also, your patterns need to have a delimiter. $regexExpr = "~localhost/view.php\?s=[0-9]+&a=[0-9]+~" need to apply that to your other patterns too Also you can probably make your code more efficient overall by combining those 3 preg functions and loop by using preg_replace_callback instead Quote Link to comment Share on other sites More sharing options...
dwayn Posted January 22, 2011 Author Share Posted January 22, 2011 Thanks for the reply... Yeah i did that..(Just before you replied ) but still NO OUTPUT ... I escaped '?' and applied delimiter too '~' .. still echo "$message" ; prints nothing...... Any reason that you can see? or some mistake? P.S. Thanks for the suggestion..I'll definately do that Quote Link to comment Share on other sites More sharing options...
.josh Posted January 22, 2011 Share Posted January 22, 2011 I'm guessing you don't have error reporting turned on... ...looks like based on comment in your code, with that last preg_replace() you are trying to use a single pattern but an array of replacements (string>array). With preg_replace, the pattern>replace can be string>string, array>string or array>array, but not string>array. So you basically have three choices. First choice would be to put that last preg_replace() in a loop (you can put it in your current foreach loop or use another loop) and then limit the preg_replace() to one replacement at a time (you do this with optional 4th argument of preg_replace()). This will only really work if your replacement is changed to the point that the pattern will not match it again after the replacement (I have no idea whether or not your replacement does this because you didn't post that part of your script). 2nd choice would be to basically make an array for your pattern argument that has same amount of elements as your replacement and each element of the array just has the same pattern. You will need to use 4th argument for this way too, and it also would depend on same thing as option 1 as far as whether or not the pattern will rematch the replacement. 3rd choice is to move forward with the preg_replace_callback() option, which is what I vote you should do, as it is cleaner and built for this exact type of scenario. Quote Link to comment Share on other sites More sharing options...
dwayn Posted January 22, 2011 Author Share Posted January 22, 2011 Hi there, thanks for the reply...i just tried things using preg_replace_callback(), i think the situation is just the same.... For every match in subject i have different elements in replacement array.. like e.g if i get two matches in subject string, than i want 1st match should be replaced with some string and other match with some other string.. If i use preg_replace_callback() , here i will be having same replacement string for all the matches.. Isn't it? Any workaround? Quote Link to comment Share on other sites More sharing options...
.josh Posted January 22, 2011 Share Posted January 22, 2011 no...preg_replace_callback() will effectively allow you to do string>array for pattern>replacement, though it actually lets you do a lot more than that. You make a call to a specified function for each match found, as it is found, and replace the found item with whatever you return from the function. 1. Match 2. Call function, passing match 3. replace match with whatever is returned from function 4. repeat 1-3 until no more matches So for instance: function someFunction($matches) { $m = $matches[0]+1; return $m; } $content = "123"; echo $content . "<br/>"; $content = preg_replace_callback("~\d~","someFunction",$content); echo $content; output: 123 234 So you would basically do function someFunction ($matches) { // $matches[0] is the full current match // $matches[1] is whatever the value of your s param is // $matches[2] is whatever the value of your a param is // do whatever calculations, assumed resulting, final string you want to replace the pattern with is put into $replacement return $replacement } $regexExpr = "~localhost/view.php\?s=([0-9]+)&a=([0-9]+)~" ; $message = preg_replace_callback($regexExpr, "someFunction", $message); edit: I edited it to use captured groups in the regex so you can skip having to do that foreach loop you had... Quote Link to comment Share on other sites More sharing options...
dwayn Posted January 22, 2011 Author Share Posted January 22, 2011 Ok..that was a stupid question... I got it all working.. Just one small query with another regex.. preg_match_all($regexExpr2, $value, $numbers, PREG_PATTERN_ORDER); echo "$numbers[0][0] $numbers[0][1]"; is printing Array[0] Array[1] instead of 2 matches that are found in string $value.... So Confused.. Any suggestion? P.S talking about the edit you did, suppose i get two matches , each match having 2 groups that i want ultimately... How will i use it? $matches[0] will be an array containing two full match string, $matches[1] will be an array having 1st group elements of 2 complete matches and so on?? P.P.S i tried it out.. Thanku so much for your reply.. really a help.. Thanks a lot. Quote Link to comment Share on other sites More sharing options...
.josh Posted January 22, 2011 Share Posted January 22, 2011 need to see the actual pattern, what $regexExpr2 is Quote Link to comment Share on other sites More sharing options...
.josh Posted January 22, 2011 Share Posted January 22, 2011 okay maybe it might help if you explain what you are actually trying to do with the matched stuff and what you are trying to replace it with. For example, if I have this: <?php function someFunction ($matches) { // $matches[0] is the full current match // $matches[1] is whatever the value of your s param is // $matches[2] is whatever the value of your a param is echo "<pre>";print_r($matches); echo "</pre>"; // do whatever calculations, assumed resulting, final string you want to replace the pattern with is put into $replacement return $replacement; } $message = "hen an unknown printer took a galley of type and localhost/view.php?s=324&a=2433 scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic localhost/view.php?s=33&a=222 typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing"; $regexExpr = "~localhost/view.php\?s=([0-9]+)&a=([0-9]+)~" ; $message = preg_replace_callback($regexExpr, "someFunction", $message); ?> I get the following output: Array ( [0] => localhost/view.php?s=324&a=2433 [1] => 324 [2] => 2433 ) Array ( [0] => localhost/view.php?s=33&a=222 [1] => 33 [2] => 222 ) Each time there is a match, the function is called and I dump out the contents of $match. As you can see, $matches[0] is the full current match, $matches[1] is the first captured group (the value of s param in the string) and $matches[2] is the value of the 2nd captured group in your string (the a param) Quote Link to comment Share on other sites More sharing options...
dwayn Posted January 22, 2011 Author Share Posted January 22, 2011 Yeah.. i got it ... Thanks again Quote Link to comment Share on other sites More sharing options...
dwayn Posted January 29, 2011 Author Share Posted January 29, 2011 Hey Crayon Violent, i got stuck again.. How to pass some extra arguments to the callback function.. Like e.g. $matches is the only argument that is being passed currently.. what if i want to pass another variable $story to callback function so that i can append matched text to this variable $story? Any suggestions? Quote Link to comment Share on other sites More sharing options...
dwayn Posted January 29, 2011 Author Share Posted January 29, 2011 well, situtaion is kinda like this.... I have text(not links) which is stored in $text and in this text i have some words in this format "Step:111.Description:this is testing of &.Link:http://localhost/view.php?s=2&a=4.End" what i want to do is to replace these words with the number specified after Step: and add lines in these format at the end of the $text. Format = "[number after Step:] - <a href="link specified after Link:">(Text specified after Description:)</a> so here is the code i wrote: $rege= "~Counter:([0-9]+)\.Title:([a-z|A-Z| |&|0-9|*|,]+)\.Url:(http://localhost/view.php\?s=[0-9]+&a=[0-9]+)\.End~"; $message=preg_replace_callback($rege,create_function('$matches,$message','$message=$message."<br/>[$matches(1)]-<a href=\"$matches[3]\">$matches[2]</a>"; return "[$matches(1)]";'),$message); Errors: PHP Notice: in file /view.php(1494) : runtime-created function on line 1: Missing argument 2 for __lambda_func() Also, the regex expression is not matching the text.... I tried it matching online , it worked there but not in the code..don't know why.. Please help! Quote Link to comment Share on other sites More sharing options...
sasa Posted January 30, 2011 Share Posted January 30, 2011 try <?php $message = 'Step:111.Description:this is testing of &.Link:http://localhost/view.php?s=2&a=4.End'; $message = preg_replace('/Step:(\d+)\.Description:(.+?)\.Link:(.+?)\.End/', '\1 - <a href="\3">\2</a>', $message); echo $message; ?> Quote Link to comment Share on other sites More sharing options...
dwayn Posted January 30, 2011 Author Share Posted January 30, 2011 try <?php $message = 'Step:111.Description:this is testing of &.Link:http://localhost/view.php?s=2&a=4.End'; $message = preg_replace('/Step:(\d+)\.Description:(.+?)\.Link:(.+?)\.End/', '\1 - <a href="\3">\2</a>', $message); echo $message; ?> there is not just 1 word of this format in $text ... there are many words of this format.... Also, could you please explain your regex expression.. I didn;t understand it! Quote Link to comment Share on other sites More sharing options...
sasa Posted January 30, 2011 Share Posted January 30, 2011 are you try it <?php $message = 'Step:111.Description:this is testing of &.Link:http://localhost/view.php?s=2&a=4.Endbla b la Step:2211.Description:this is testing of iiii&.Link:http://localhost/view.php?s=2&a=994.End xxxx Step:113.Description:this is testing of &2.Link:http://localhost/view.php?s=992&a=4.End'; $message = preg_replace('/Step:(\d+)\.Description:(.+?)\.Link:(.+?)\.End/', '\1 - <a href="\3">\2</a>', $message); echo $message; ?> as you see it works for multiple replaces Explain regex / - start of regex Step: - literaly (\d+) - one or more digits () means grab subparten, used in replace part as \1 \.Description: - literaly (.+?) - one or more caracther (? means shorten posible string) subparten \2 \.Link: literaly (.+?) - one or more characters \.End literaly / Quote Link to comment Share on other sites More sharing options...
.josh Posted January 30, 2011 Share Posted January 30, 2011 Hey Crayon Violent, i got stuck again.. How to pass some extra arguments to the callback function.. Like e.g. $matches is the only argument that is being passed currently.. what if i want to pass another variable $story to callback function so that i can append matched text to this variable $story? Any suggestions? There is no graceful way to pass additional arguments to a function in a xxx_callback(). As of php 5.3 you can but even then the syntax readability is less than desirable. What I do is instead of passing data as arguments, I make it accessible within the function by declaring it as a global variable within the function and then pass it to a static variable (variable persists from function call to function call but stays within function scope) or non-static (variable lasts for duration of single function call) depending on my needs. Example: function someFunction ($matches) { // $matches[0] is the full current match // $matches[1] is whatever the value of your s param is // $matches[2] is whatever the value of your a param is // declare $someVar as a global variable so the function can access it global $someVar; // declare a static variable static $_someVar; // assign the global variable to the static variable and use the static variable if(!$_someVar) $_someVar = $someVar; // do whatever calculations, assumed resulting, final string you want to replace the pattern with is put into $replacement // use $_someVar as the variable you wanted to pass (don't touch $someVar) return $replacement; } // end someFunction $someVar = 123; // this is the variable you want to pass to someFunction $message = "hen an unknown printer took a galley of type and localhost/view.php?s=324&a=2433 scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic localhost/view.php?s=33&a=222 typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing"; $regexExpr = "~localhost/view.php\?s=([0-9]+)&a=([0-9]+)~" ; $message = preg_replace_callback($regexExpr, "someFunction", $message); The idea here is that you have a variable you want to pass to the callback function, but instead of passing it as an argument, you declare it within someFunction() as global so you can access it. But then you immediately assign it to a static variable and use the static variable instead (so that you aren't using/changing the global variable). Now I know some people might have a knee-jerk reaction to say using a global within a function is evil incarnate because it defeats the purpose of having scope, but IMO this is one of the few times where using globals within a function is acceptable. IMO this makes the code more readable. Also, I don't actually USE the global variable. I just declare it as a global variable and copy it to a static variable and use the static variable. Note: I ONLY do this for xxx_callback() type functions. I do not do this for calling other functions.. Quote Link to comment 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.