#!/bin/sh
# -*- tcl -*-
# The next line is executed by /bin/sh, but not tcl \
exec tclsh "$0" ${1+"$@"}
我对上述两件事感到困惑。
我知道 $0 是文件名,我们也使用 argv0 获取文件名。
并且 argv 是文件的参数,与 "$@" 相同,但是为什么我们要在 sritps 中同时使用这两个东西。
混淆是因为$0
并且${1+"$@"}
不是 tcl 语法。它是 shell 语法,与 tcl 无关。
当你有这样的脚本,并从命令行运行它时,系统会认为它是一个 shell 脚本,并将开始运行每一行,就好像它是一个 shell 命令一样。在这一点上,argv0
类似的变量不存在。
因为这实际上是一个 tcl 脚本。我们希望 shell 做的第一件事是停止 shell 并启动 tclsh。为此,我们执行 tclsh。此外,我们必须确保——使用 shell 语法——将参数正确地传递给 tclsh。因此,我们必须使用$0
和类似的构造。一旦 tclsh 启动并且 shell 不再执行,它就会$0
消失并被argv0
设置。
$0 用于 tcl 脚本路径,${1+$@} 表示“所有参数,如果设置了第一个参数”,因此,
exec tclsh $0 ${1+$@}
意味着在停止 shell 之后,通过传递脚本文件(通过 $0)和其余参数(通过 ${1+$@})来执行 tclsh
当 tclsh 启动时,像 argv、argv 这样的 tcl 变量就会出现。
#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" ${1+"$@"}
这种方法具有三个优点。首先,tclsh 二进制文件的位置不必硬连线到脚本中:它可以在您的 shell 搜索路径中的任何位置。其次,它绕过了前一种方法中 30 个字符的文件名限制。第三,即使 tclsh 本身是一个 shell 脚本,这种方法也可以工作(在某些系统上这样做是为了处理多个体系结构或操作系统:tclsh 脚本选择几个二进制文件之一来运行)。这三行使 sh 和 tclsh 都处理脚本,但 exec 仅由 sh 执行。sh 先处理脚本;它将第二行视为注释并执行第三行。exec 语句导致 shell 停止处理,而是启动 tclsh 以重新处理整个脚本。当 tclsh 启动时,它将所有三行视为注释,
然而,
argv : 参数变量列表
argc : 参数变量列表计数
argv0 :参数变量列表中的第一个