views:

102

answers:

4

I'm now dealing with uri like /page.html?k1=1&k2=2

$str = preg_replace('/[&\?]' . $k . '=[^&]*/',"",$str);

The above aims to delete $k related part in uri,but will also delete ? wrongly.

How to do the right thing?

+3  A: 

Try this:

preg_replace('/(?:(\?)|&)' . $k . '=[^&]*/', '$1', $str)

You should additionally use preg_quote on $k.

Edit    Here’s an extended version of the above that should fix the problem described by beggs:

/(?:(\?)|&)arg=[^&]*(?(1)(?:&|$))/

The (?(1)(?:&|$)) epxression is a conditional expression that is used if the first group found a match. So if ? is found, the trailing & of that parameter is removed.

Gumbo
+1  A: 

It's deleting the "?" because you have included it in the match and are using an empty replace. To remove the variable matching "$k" and leave the "?" use the code Gumbo provided, but be aware that when "$k" == "k1" the result string will be "/page.html?&k2=2", note the left over "&".

beggs
+1  A: 

If you're dealing with URLs and query strings, you might want to use parse_url to extract URL components and parse_str to extract query string bits. It'll be much easier to manipulate an array of arguments instead of dealing with regexes. You can then use http_build_query to put it back together again.

Charles
+3  A: 

Hi,

To remove a portion of a querystring, I would not use regular expressions, but functions that exist to manipulate URLs.

For instance, considering this portion of code, which uses the parse_url function to extract parts of an URL :

$url = '/page.html?k1=1&k2=2';
$parts = parse_url($url);
var_dump($parts);

You'll get :

array
  'path' => string '/page.html' (length=10)
  'query' => string 'k1=1&k2=2' (length=9)

You can now extract the informations contained in the original query string, with parse_str :

$params = array();
parse_str($parts['query'], $params);
var_dump($params);

Which will get you :

array
  'k1' => string '1' (length=1)
  'k2' => string '2' (length=1)

Now, to remove one parameter, you can test if it exists in the array, and, if yes, remove it :

$to_remove = 'k1';
if (array_key_exists($to_remove, $params)) {
    unset($params[$to_remove]);
}
var_dump($params);

Which now gives the following array of parameters :

array
  'k2' => string '2' (length=1)

And, finally, you can put back the pieces together, using http_build_query :

$new_query = http_build_query($params);
var_dump($new_query);

And you get :

string 'k2=2' (length=4)

You now just have to inject this after your URL ;-)


Some might say it's a bit longer... I would answer that, looking at this code, one immediatly inderstands its purpose -- which is not quite the case with a complex regex.

Pascal MARTIN