Reputation: 3267
I have the following code in TCL:
regexp "\[00]\[00].info.age\\s*=\\s*26" "[00][00].info.age = 26"
but it does not match, what is the problem and how to fix it?
Upvotes: 0
Views: 278
Reputation: 4043
First of all, in the second parameter, you should escape the [
putting the following string, "\[00]\[00].info.age = 26"
, otherwhise Tcl will perform command execution and return invalid command name "00".
Then, the problem is that you are using quotes "
for grouping the pattern, but in quotes substitutions happen. Therefore, your escaped [
avoid command execution, but is passed as a simple bracked to the regexp
command which, in turns, sees it as the beginning of a bracked expression.
You have two choices, the first one is the following
regexp "\\\[00]\\\[00].info.age\\s*=\\s*26" "\[00]\[00].info.age = 26"
quite ugly but does the job: in the pattern, the first \\
is substituted by a single \
, the following \[
is substituted by a [
and the pattern becomes this literal string
\[00]\[00].info.age\s*=\s*26
The other way is to replace the quoting characters in the pattern with the curly braces, to avoid the parser substitution step:
regexp {\[00]\[00].info.age\s*=\s*26} "\[00]\[00].info.age = 26"
You also have to remove one \
from each \\s
because you don't need to escape it anymore.
Edit: a little explaination
The parser performs substitutions before the regexp
command is executed.
The parser sees the grouping character "
, so it performs substitutions inside it. Inside "..."
, a pair of coupled [...]
are a command execution, so the inner command is called and its result replaces the [...]
string.
To avoid this substitution, you need to escape the [
using \[
.
After that, the parser did its job and it's the turn of regexp
, which is executed.
If the pattern you pass to it contains a [...]
group, you are giving it a bracket expression, that is a set of characters to choose among.
You don't want that, because you must match a literal [
, so you have to tell regexp
to drop its special meaning: to do that, you have to escape it, by placing a backslash \
in front of it, that is \[
.
Your code, then, must pass a backslash followed by an opening bracket to regexp
, but both are special characters for Tcl too and they have a special meaning to the Tcl parser, which is called first.
So, to remove the special meaning of the backslash, the Tcl parser must see two backslashes: these are the first two backslashes you see in the pattern, \\
; to remove the special meaning of the opening bracket, the Tcl parser must see it escaped by a backslash: this is the third backslash you see in the pattern, \[
.
I hope this is clearer :)
Upvotes: 1
Reputation: 71538
As mentioned in my previous answer, use braces and avoid all double escaping:
% set str "\[00]\[00].info.age = 26"
[00][00].info.age = 26
% regexp {\[00]\[00].info.age\s*=\s*26} $str
1
Otherwise, you'll have to double escape (in this case triple escape? Since []
are used to call commands. I'm not sure how to call it...):
% set str "\[00]\[00].info.age = 26"
[00][00].info.age = 26
% regexp "\\\[00]\\\[00].info.age\\s*=\\s*26" $str
1
Upvotes: 2