Search code examples
linuxgreptclexeccsh

Tcl exec on grep returns "grep: nothing to repeat", whereas normal LINUX gives right answer


Here is what happens when I run a command using the cshell:

find /projects/corpeng/members/ldagan/adm/utils/Synopsys/CCK/shared_tcl_code -name "*.tcl" | grep -v regression | xargs grep -Plc "^[ ]*namespace[ ]+eval[ ]+DlgViolationKeepProcs "
> /projects/corpeng/members/ldagan/adm/utils/Synopsys/CCK/shared_tcl_code/DlgViolationKeepProcs.tcl

So far, so so good. However, see what happens when I try to do the same in TCL 8.4:

exec find /projects/corpeng/members/ldagan/adm/utils/Synopsys/CCK/shared_tcl_code -name "*.tcl" | grep -v regression | xargs grep -Plc "^[ ]*namespace[ ]+eval[ ]+DlgViolationKeepProcs "
> grep: nothing to repeat

Why? Any ideas?
Thanks.


Solution

  • The problem is that [] in double-quotes is processed as a Tcl command substitution. In particular, [ ] gets replaced with the empty string, i.e., deleted! The simplest fix is to put the grep term in {braces} to inhibit substitutions, though putting a backslash (\) in front of the [ also works.

    Let's make your code a little easier to read too by using some strategic variables:

    # Where to search from; often a nice thing to separate out
    set basedir /projects/corpeng/members/ldagan/adm/utils/Synopsys/CCK/shared_tcl_code
    
    # What to look for; note the braces!
    set term {^[ ]*namespace[ ]+eval[ ]+DlgViolationKeepProcs }
    
    exec find $basedir -name "*.tcl" | grep -v "regression" | xargs grep -Plc $term
    

    It would also work if you'd said:

    set term "^\[ ]*namespace\[ ]+eval\[ ]+DlgViolationKeepProcs "
    

    But experience tells me to try to avoid using backslashes more than necessary; they are more confusing in the longer term.