Executing Other Programs

A common complaint from beginners trying to execute other programs from Tcl is “It works in the shell but not in Tcl.” Let’s suppose you write a small Bourne shell script to strip the first word of each line and return a count of unique words:

$ awk '{print $1}' somefile | sort-u | wc -l

This works fine when you execute it on your terminal. You then cut and paste the line into your Tcl program, setting a variable to the number of unique words:

set numWords [exec awk '{print $1}' somefile | sort -u | wc -l]

Tcl will report an error “can’t read ’1’: no such variable.” You might try to fix that error by quoting $1 as \$1, but that causes another error message, “awk: syntax error near line 1.” You ask, “What gives? It worked as a shell command but fails under Tcl!”

Tcl’s exec command executes other programs directly without the use of the shell. Tcl’s exec goes about collecting arguments, building pipelines, and invoking another program, all according to Tcl syntax rules. A single quote character (') has no special significance, unlike in most user shells. Tcl applies its parsing rules and breaks up the command pipeline into Tcl words. Thus, the awk program in awk’s first argument is passed as:

'{print

and not as the desired string:

{print $1}

as it is passed with a command-line user shell (Bourne shell, C shell, Korn shell, Bash, etc.).

The simple fix is to use Tcl quoting instead of shell quoting! Replace the single quotes (') with Tcl braces:

set numWords [exec awk ...

Get Tcl/Tk in a Nutshell now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.