3

I tried

puts [regexp "(\[0-9]{1,3})\.(\[0-9]{1,3})\.(\[0-9]{1,3})\.(\[0-9]{1,3})" 192.168.1.10]

answer is 1.

But if I use

puts [regexp "(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})" 192.168.1.10]

(replaced \[0-9] with \d) answer is 0.

Can someone please tell me why?

Jerry
  • 70,495
  • 13
  • 100
  • 144
Ram
  • 27
  • 5
  • 1
    try use \\d instead of \d – joe Dec 22 '14 at 09:46
  • If one of the answers below fixes your issue, you should accept it (click the check mark next to the appropriate answer). That does two things. It lets everyone know your issue has been resolved, and it gives the person that helps you credit for the assist. [See here](http://meta.stackexchange.com/a/5235/204922) for a full explanation. – Jerry Dec 22 '14 at 10:51

2 Answers2

5

You should either escape the backslash in the \d as \\d when used with double quotes.

puts [regexp "(\\d{1,3})\.(\\d{1,3})\.(\\d{1,3})\.(\\d{1,3})" 192.168.1.10]

Or you have to use braces.

puts [regexp {(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})} 192.168.1.10]

Note : With braces, variable substitution won't happen.

Dinesh
  • 16,014
  • 23
  • 80
  • 122
  • 1
    If you want to use braces to avoid backslash evaluation, you should not surround it with yet another level of double quotes, because this makes backslashes to be evaluated anyway. The correct answer should be: `puts [regexp {\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3}} 192.168.1.10]` – Googie Dec 22 '14 at 10:14
  • @Googie uh yes, but the 'should be' is in my answer. You also have unbalanced parens there which will cause the function to complain :) – Jerry Dec 22 '14 at 10:22
  • Ya I got it Thanks Dinesh,Googie and Jerry – Ram Dec 22 '14 at 10:32
3

The issue here is not really the difference between \d and [0-9] but rather the way you are handling those two expressions in regex. In Tcl, double quotes allow a first level of substitution. It is only when that level of substitution completes, that the result is passed to the regexp function.

So with that view, what is actually passed to the regexp function in the two cases are:

([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3})

and

(d{1,3}).(d{1,3}).(d{1,3}).(d{1,3})

Which obviously doesn't match the string you provided. Something like dd.ddaddfdd would, however (remember that . matches any single character!).

Remember that backslashes are substituted in Tcl, just like $ or [ ... ] whenever possible (i.e. when strings are provided without braces). To get a literal backslash, you thus would do (with that current formatting):

([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})

and

(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})

Or to avoid the pain of doing that, use braces:

regexp {([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})} 192.168.1.10

and

regexp {(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})} 192.168.1.10

Something else I would mention here is that you don't need the parentheses for validation if you are not using them for grouping, so this should suffice and improve the speed of your script:

regexp {[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}} 192.168.1.10

And if you want the answer to your title, there is a difference between the \d and [0-9]. The most popular question on stackoverflow has been raised from C# but this also applies in Tcl is this one which shows that \d matches much more than the numbers 0 through 9.

Community
  • 1
  • 1
Jerry
  • 70,495
  • 13
  • 100
  • 144