Most '''[Unix] shells''' belong to either the [Bourne Shell] family or the [csh] family, although other alternative shells exist. Tcl may not be a direct descendant of any of the preexisting shells, but it certainly shares some of their traits, notably [EIAS], where it Tcl is more disciplined and consistent than other shells. ** See Also ** [gush]: an attempt to write an updated Unix shell/terminal in Tcl. [Tcl Heritage]: a number of Unix shell languages influenced the design of Tcl. [Tcl and other languages]: an listing of languages that have crossed paths with Tcl [Playing Bourne shell]: emulating shell syntax and commands in Tcl ** Reference ** [http://faqs.org/faqs/unix-faq/shell/shell-differences/%|%UNIX shell differences and how to change your shell (Monthly Posting)]: an introduction to Unix Shells, comparing some oft he more common ones. ** Tcl for Shell Programmers ** Tcl shares a key feature with other Unix shells: Each line is a command, and the first word of each line is the name of the command. It isn't necessary to quote simple strings: ======none #! /bin/env sh echo hello ====== ====== #! /bin/env tclsh puts hello ====== Where Unix shells typically use the term, ''expansion'', Tcl uses the term, ''[Dodekalogue%|%substitution]''. In Unix shells, a variable is a named parameter. Tcl simply uses the term, ''variable'', and doesn't have special parameters which are not assignable in scripts. Shell parameter expansion is indicated by `$` : ======none echo $name ====== Tcl variable substitution also uses `$`: ====== puts $name ====== In Bourne-compatible shells, the output a command can be captured using the following notation: ======none a=`date` ====== or ======none a="$(date)" ====== In Tcl, the same thing is accomplished using brackets to introduce [script substitution] and `[exec]` to captures the output of an external command: ====== set a [exec date 2>@stdout] ====== Unlike other Unix shells, Tcl itself has no syntax for I/O redirection, deferring instead to `[exec]`, which implements its own syntax for the arguments that are passed to it. By design, Tcl syntax remains minimal, while individual commands are free to interpret arguments passed to them in arbitrarily complex ways. Unix shells use braces to delimit the variable name from surrounding characters: ======none echo one${two}three ====== Tcl does the same: ====== puts one${two}three ====== But the similarity stops there. Unix shells provide further parameter expansion syntax for array and string length, indexing, ranges, substitution, default values, alternate values, conditional assignment, pattern matching of array values, and listing of array keys. Tcl, on the other hand, only provides syntax for selecting items in an array: ====== puts $person(name) ====== All the remaining parameter expansion functionality of Unix shells is provided in Tcl via commmands rather than special syntax. For example, in a Unix shell, to extract the range of a string: ====== puts ${name:2:4} ====== In Tcl, `[string range]` performs that operation: ====== puts [string range $name 2 4] ====== In Unix shells, double quotes protect whitespace while still allowing parameter expansion, command expansion, and backslash escaping: ======none echo "$(greeting), $name" ====== In Tcl, double quotes do the same, except that double quotes must completely enclose a word to have special meaning: ====== puts "[greeting], $name" ====== In Tcl, double quotes have no special meaning in the middle of a word as they do in other shells. For example, contrast the the following scripts: ======none #! /bin/env bash var1=one"two"'three'four ====== ====== #! /bin/env tcsh var1=one"two"'three'four ====== ====== set var1 one"two"'three'four ====== In the Unix shells, the value of `var1` is `onetwothreefour`, but in Tcl, the value is `one"two"'three'four`. The double and single quotes are retained as part of the value because they occurr within a word rather than enclosing a word. Unix shells use the single quote character to delimit strings that escape all forms of expansion: ======none sentence='a value of $42.11 (no kidding); This is just a string. `backquotes` mean nothing special, either' ====== In Tcl, braces `{}` serve the same purpose. As with double quotes, braces must entirely enclose a word in order to have special meaning. Within braces, embedded brace pairs are allowed, and an unpaired brace character preceded by a backslash is not counted when searching for the closing brace at the end of the word: ====== set a {a value of $42.11 (no kidding); {This is just a string}. `backquotes` mean nothing \{ special, either} ====== Apart from quoting, the big difference between Tcl and other Unix shells is that substitutions never change word boundaries, whereas in other Unix shells, word splitting occurs after substitution, which means that substitution can affect the number of words in a command: ======none #! /bin/env bash var1="three four" var2=( one two $var1 five ) echo ${#var2[*]} # -> 5 ====== ====== #! /bin/env tclsh set var1 {three four} set var2 [list one two $var1 five] puts [llength $var2] ;# -> 4 ====== Tcl provides `[{*}]` to change the number of words in a command. Any word preceded by `{*}` is interpreted as a [list], the items of which become individual words in the command: ====== #! /bin/env tclsh set var1 {three four} set var2 [list one two {*}$var1 five] puts [llength $var2] ;# -> 5 ====== Finally, other shells have built-in syntax for things like piping I/O between commands, executing scripts in a subshell, grouping commands for execution, evaluating mathematical expressions, equality testing of mathematical expressions, iterating through values, for and while loops, simple user interfaces, switch statements, conditional statements, and function definitions. Tcl does away with the syntax for all those features, and instead implements them as commands. By becoming less, Tcl is able to become more. With the help of built-in commands such as `[upvar]`, `[uplevel]`, and `[tailcall]`, it is possible to implement [new control structures] and to replace any built-in commands with customized versions. In this way, can be transformed by into a [domain-specific language%|%language specialized for a specific purpose]. ** Advantage Tcl: [list%|%List] Represenation ** In most Unix shells, it isn't exactly straightforward to pass an array/list of arbitrary values between commands. Consider the following array. ====== res=(one "two:three four" five) ====== One way to write a shell function that appends an element to an array is ====== arr_append () { eval $1'[${#'$1'[*]}]="$2"' } a1=(one "two:three four" five) arr_append a1 "six seven" ====== , which is painful both to read and to write. It's more simple in Tcl: ====== lappend a1 {six seven} ====== Even if `[lappend]` didn't exist, it would still be more simple in Tcl: ====== set a1 [concat $a1 [list {six seven}]] ====== <> Unix