0

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?

user2131316
  • 3,111
  • 12
  • 39
  • 53

2 Answers2

2

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
Community
  • 1
  • 1
Jerry
  • 70,495
  • 13
  • 100
  • 144
1

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 :)

Marco Pallante
  • 3,923
  • 1
  • 21
  • 26
  • thank you for your answer, but I still do not know why we need to put triple \ in front of [, we need to escape [, so \\[, and we need to escape \ in front of \\[, so \\\[, is it not enough? – user2131316 Aug 12 '13 at 10:58
  • No, it's not enough. I added a longer explaination to my answer. Let's see if my words are clearer, now :) – Marco Pallante Aug 12 '13 at 11:25
  • but why the ] is not need to be escaped? – user2131316 Aug 30 '13 at 11:32
  • Because you already escaped the `[`, so it's not taken as *command substitution* starting sign, and then the `]` doesn't have any special meaning. – Marco Pallante Aug 30 '13 at 14:57