Hi,
I am using the answer-mode as it provides formatting options.
The TCL
regsub
does a substitution in a string based on a search pattern.
The search pattern is a interpreted as a regular expression.
(And this makes it more flexible than the
string map
solution but may consume more CPU cycles.
So for a lot of other use cases the solution provided by Stanislas will be the better one.)
Here is the explanation for the regsub command as used above:
regsub -nocase -all {(^identity=[^;&]*[;&]?|[;&]identity=[^;&]*)} [HTTP::query] "" new_query
The switches
-nocase
and
-all
allow to search and replace all matching ranges and handle the search pattern case insensitive. If you are expecting a single instance of the query parameter only and you are sure about upper/lower case characters you can go without both params.
The search pattern is placed between curly braces
{...}
followed by the string to search (in our case the expanded
[HTTP::query]
followed by the string which is replacing the found ranges (in our case an empty string
""
) followed by a variable which is containing the modified string (in our case the new resulting http query represented by the variable
new_query
).
The search pattern consists actually of two patterns separated by a pipe
|
and surrounded by parenthesis
()
.
This approach allows to search for different search patterns.
In our case it is required as we may expect the query parameter at the beginning, in the middle of, at the end of or being the only query parameter.
Lets start with the first pattern of
^identity=[^;&]*[;&]?
:
The circumflex
^
requires the following pattern to be found at the beginning of the search string (query parameter is the first or first and only parameter). It is followed by a literal string of
identity=
which is matching the name of your specific query parameter which has to be replaced. (You may want to replace it i.e. by
GetOan=
.) If you want this pattern to be case insensitive you will better write it all lowercase and use the
-nocase
switch as described above. The term
[^;&]*
now finds all or none directly following characters not matching ";" or "&". In this case the circumflex symbol
^
at the beginning of the class definition negates the search to exclude the known query parameter separators from matching (in regex characters may have different meanings depending on the context they are used). This part of the search pattern will actually find the value of the query parameter (in your case it is the variable part). It will be followed (multiple parameters) or not (single parameters only) by a ";" or "&" separator character. The one instance or not is expressed by the question mark
?
character.
The second pattern of
[;&]identity=[^;&]*
looks for matches if the query parameter is embedded between others or can be found at the end. In both cases we have a leading separator character of ";" or "&" which is indicated by the class of
[;&]
(one of the characters between the brackets has two match; please note, that no quantifier like
*
or
?
as above is used). Now we try again a literal match for your literal query parameter name including the "=". As in the first search pattern we now have to find the associated parameter value which must not contain ";" or "&" as they are used as separators. This is finally done again by using
[^;&]*
. So it will actually find as well a query parameter with an empty value as the
*
finds all and nothing.
Thats it. I wont call me an expert in regex and my terminology may not be 100% accurate.
To adopt it to another (single and case sensitive) query parameter you will go with:
regsub {(^GetOan=[^;&]*[;&]?|[;&]GetOan=[^;&]*)} [HTTP::query] "" new_query
I hope, this answers your question.
Thanks, Stephan