user2131316
user2131316

Reputation: 3267

how to match "[]" in TCL?

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

Answers (2)

Marco Pallante
Marco Pallante

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

Jerry
Jerry

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

Related Questions