Regular expression to remove one parameter from query string

Posted by Kip on Stack Overflow See other posts from Stack Overflow or by Kip
Published on 2009-12-03T20:27:54Z Indexed on 2010/04/12 23:13 UTC
Read the original article Hit count: 874

Filed under:
|

I'm looking for a regular expression to remove a single parameter from a query string, and I want to do it in a single regular expression if possible.

Say I want to remove the foo parameter. Right now I use this:

/&?foo\=[^&]+/

That works as long as foo is not the first parameter in the query string. If it is, then my new query string starts with an ampersand. (For example, "foo=123&bar=456" gives a result of "&bar=456".) Right now, I'm just checking after the regex if the query string starts with ampersand, and chopping it off if it does.

Example edge cases:

Input                    |  Output
-------------------------+-----------------
foo=123                  |  (empty string)
foo=123&bar=456          |  bar=456
bar=456&foo=123          |  bar=456
abc=789&foo=123&bar=456  |  abc=789&bar=456


Edit

OK as pointed out in comments there are there are way more edge cases than I originally considered. I got the following regex to work with all of them:

/&foo(\=[^&]*)?(?=&|$)|^foo(\=[^&]*)?(&|$)/

This is modified from Mark Byers's answer, which is why I'm accepting that one, but Roger Pate's input helped a lot too.

Here is the full suite of test cases I'm using, and a Perl script which tests them.

Input                    | Output
-------------------------+-------------------
foo                      | 
foo&bar=456              | bar=456
bar=456&foo              | bar=456
abc=789&foo&bar=456      | abc=789&bar=456
foo=                     | 
foo=&bar=456             | bar=456
bar=456&foo=             | bar=456
abc=789&foo=&bar=456     | abc=789&bar=456
foo=123                  | 
foo=123&bar=456          | bar=456
bar=456&foo=123          | bar=456
abc=789&foo=123&bar=456  | abc=789&bar=456
xfoo                     | xfoo
xfoo&bar=456             | xfoo&bar=456
bar=456&xfoo             | bar=456&xfoo
abc=789&xfoo&bar=456     | abc=789&xfoo&bar=456
xfoo=                    | xfoo=
xfoo=&bar=456            | xfoo=&bar=456
bar=456&xfoo=            | bar=456&xfoo=
abc=789&xfoo=&bar=456    | abc=789&xfoo=&bar=456
xfoo=123                 | xfoo=123
xfoo=123&bar=456         | xfoo=123&bar=456
bar=456&xfoo=123         | bar=456&xfoo=123
abc=789&xfoo=123&bar=456 | abc=789&xfoo=123&bar=456
foox                     | foox
foox&bar=456             | foox&bar=456
bar=456&foox             | bar=456&foox
abc=789&foox&bar=456     | abc=789&foox&bar=456
foox=                    | foox=
foox=&bar=456            | foox=&bar=456
bar=456&foox=            | bar=456&foox=
abc=789&foox=&bar=456    | abc=789&foox=&bar=456
foox=123                 | foox=123
foox=123&bar=456         | foox=123&bar=456
bar=456&foox=123         | bar=456&foox=123
abc=789&foox=123&bar=456 | abc=789&foox=123&bar=456

Test script (Perl)

@in = ('foo'     , 'foo&bar=456'     , 'bar=456&foo'     , 'abc=789&foo&bar=456'
      ,'foo='    , 'foo=&bar=456'    , 'bar=456&foo='    , 'abc=789&foo=&bar=456'
      ,'foo=123' , 'foo=123&bar=456' , 'bar=456&foo=123' , 'abc=789&foo=123&bar=456'
      ,'xfoo'    , 'xfoo&bar=456'    , 'bar=456&xfoo'    , 'abc=789&xfoo&bar=456'
      ,'xfoo='   , 'xfoo=&bar=456'   , 'bar=456&xfoo='   , 'abc=789&xfoo=&bar=456'
      ,'xfoo=123', 'xfoo=123&bar=456', 'bar=456&xfoo=123', 'abc=789&xfoo=123&bar=456'
      ,'foox'    , 'foox&bar=456'    , 'bar=456&foox'    , 'abc=789&foox&bar=456'
      ,'foox='   , 'foox=&bar=456'   , 'bar=456&foox='   , 'abc=789&foox=&bar=456'
      ,'foox=123', 'foox=123&bar=456', 'bar=456&foox=123', 'abc=789&foox=123&bar=456'
      );

@exp = (''        , 'bar=456'         , 'bar=456'         , 'abc=789&bar=456'
       ,''        , 'bar=456'         , 'bar=456'         , 'abc=789&bar=456'
       ,''        , 'bar=456'         , 'bar=456'         , 'abc=789&bar=456'
       ,'xfoo'    , 'xfoo&bar=456'    , 'bar=456&xfoo'    , 'abc=789&xfoo&bar=456'
       ,'xfoo='   , 'xfoo=&bar=456'   , 'bar=456&xfoo='   , 'abc=789&xfoo=&bar=456'
       ,'xfoo=123', 'xfoo=123&bar=456', 'bar=456&xfoo=123', 'abc=789&xfoo=123&bar=456'
       ,'foox'    , 'foox&bar=456'    , 'bar=456&foox'    , 'abc=789&foox&bar=456'
       ,'foox='   , 'foox=&bar=456'   , 'bar=456&foox='   , 'abc=789&foox=&bar=456'
       ,'foox=123', 'foox=123&bar=456', 'bar=456&foox=123', 'abc=789&foox=123&bar=456'
       );

print "Succ | Input                    | Output                   | Expected                \n";
print "-----+--------------------------+--------------------------+-------------------------\n";

for($i=0; $i <= $#in; $i++)
{
  $out = $in[$i];
  $out =~ s/_PUT_REGEX_HERE_//;

  $succ = ($out eq $exp[$i] ? 'PASS' : 'FAIL');
  #if($succ eq 'FAIL')
  #{
    printf("%s | %- 24s | %- 24s | %- 24s\n", $succ, $in[$i], $out, $exp[$i]);
  #}
}

© Stack Overflow or respective owner

Related posts about regex

Related posts about querystring