Jump to content

Help with Regex


dwayn

Recommended Posts

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?)

 

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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 :)

Link to comment
Share on other sites

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.

 

 

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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...

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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)

Link to comment
Share on other sites

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? :)

Link to comment
Share on other sites

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! :(

 

 

Link to comment
Share on other sites

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;
?>

Link to comment
Share on other sites

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! :(

Link to comment
Share on other sites

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

/

Link to comment
Share on other sites

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..

 

 

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.