the Bourne Shell is one of the two predominant Unix shells.
Modern variants of the Bourne Shell include
Here are some shell functions to generate a Tcl list from a sequence of values, and to load a Tcl list into an array. They're handy, among other things, for storing and loading structured data.
#! /bin/env bash : ${TCLSH:=tclsh} #generate a Tcl list from a sequence of arguments #example: mylist=$(tcllist one two three '{' ) tcllist () { "${TCLSH[@]}" - "$@" <<-'EOF' proc main {argv0 argv} { puts -nonewline [lrange $argv 0 end] } if {[catch { main $argv0 [lrange $argv[set argv {}] 1 end] } cres copts]} { puts stderr $copts puts stderr $cres exit 1 } EOF } #load a Tcl list into an array #example: tcllist_arr myarray '{one two {three four} five}' tcllist_arr () { eval $1'=()' while read -d $'\0'; do eval $1'[${#'$1'[*]}]="$REPLY"' done < <( "${TCLSH[@]}" - "${@:2:$#}" <<-'EOF' proc main {argv0 argv} { set list [lindex $argv 0] foreach item $list { puts -nonewline $item\0 } puts '' } if {[catch { main $argv0 [lrange $argv[set argv {}] 1 end] } cres copts]} { puts stderr $copts puts stderr $cres exit 1 } EOF ) }
It is well-known that csh is not fit for programming. Bourne shells also do not rise to the occasion. One big issue is their scoping rules. In the following example, $i in the second function interferes with $i in the first function:
f1 () { local i for ((i=0 ;i<10 ;i++)); do echo $i f2 done } f2 () { for ((i=0 ;i<5 ;i++)); do #do something useful : done } f1
PYK 2015-08-04: In my opinion, one of the biggest reasons not to write programs in the Bourne shell language is that subshells swallow errors. In the following example, hello is not expected to print because the interpreter should exit when the unknown variable, $x is referenced, and indeed it doesn't:
/bin/env sh set -u echo $x echo hello
In sh scripting, however, it's extremely common to run commands in a subshell and collect their output. In the following example, even hello does print even though the shell is configured as before:
/bin/env sh set -u echo $(echo $x) echo hello
Programming in a dynamic language is already adventurous enough. At least choose a sane dynamic language like Tcl. Beware the This is going to be a smallish script so I'll just write it in sh trap.
dbohdan 2015-09-02: I think there's truth to the following PYK quote from the Tcl chatroom. How Tcl and the POSIX shell respectfully go about performing substitution is what makes one a serious competitor to Lisp and the other difficult merely to loop through a list of file names with.
04:20 < pooryorick> And the secret sauce of Tcl compared to sh is that Tcl doesn't rescan substituted values. |
04:20 < pooryorick> In retrospect, I think that's Ousterhout's most remarkable contribution. |