一)特殊变量
变量名只能包含数字、字母和下划线,因为某些包含其他字符的变量有特殊含义,这样的变量被称为特殊变量。
例如,$ 表示当前Shell进程的ID,即pid,看下面的代码:
echo $$
变量 | 含义 |
---|---|
$0 | 当前脚本的文件名 |
$n | 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。 |
$# | 传递给脚本或函数的参数个数。 |
$* | 传递给脚本或函数的所有参数。 |
$@ | 传递给脚本或函数的所有参数。被双引号(” “)包含时,与 $* 稍有不同,下面将会讲到。 |
$? | 上个命令的退出状态,或函数的返回值。 |
$$ | 当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。 |
二)命令行参数
2.1) $0 and $n
其中 $0
指向实际的命令、程序、Shell 脚本或函数。
运行脚本时传递给脚本的参数称为命令行参数。命令行参数用 $n 表示,例如,$1 表示第一个参数,$2 表示第二个参数,依次类推。命令行参数 $1
、$2
、$3
、…$9
是位置参数
2.2)$* 和 $@ 的区别
$* 和 $@ 都表示传递给函数或脚本的所有参数,不被双引号(” “)包含时,都以”$1” “$2” … “$n” 的形式输出所有参数。
但是当它们被双引号(” “)包含时,”$*” 会将所有的参数作为一个整体,以”$1 $2 … $n”的形式输出所有参数;”$@” 会将各个参数分开,以”$1″ “$2” … “$n” 的形式输出所有参数。
有两个特殊参数允许一次访问所有命令行参数。$*
和 $@
在不加引号的情况下行为相同,但在加引号时有所不同。
这两个参数都指定了命令行参数。然而,"$*"
会将整个列表作为一个参数处理,参数之间用空格分隔,而 "$@"
会将整个列表分开成多个独立的参数。
可以编写如下 Shell 脚本来处理未知数量的命令行参数,无论使用 $*
还是 $@
特殊参数 −
#!/bin/bash echo "Using \$*:" for arg in $* do echo "$arg" done echo "Using \"\$*\":" for arg in "$*" do echo "$arg" done echo "Using \$@:" for arg in $@ do echo "$arg" done echo "Using \"\$@\":" for arg in "$@" do echo "$arg" done
运行:
./script_name.sh arg1 "arg2 with spaces" arg3
运行结果:
Using $*: arg1 arg2 with spaces arg3 Using "$*": arg1 arg2 with spaces arg3 Using $@: arg1 arg2 with spaces arg3 Using "$@": arg1 arg2 with spaces arg3
在这个示例中:
"$*"
将整个参数列表作为一个单一的参数处理,所有参数之间用空格分隔。"$@"
将每个参数单独处理,保留参数中的空格。
使用 "$@"
更适合处理包含空格的参数,因为它会正确保留每个参数的独立性。
2.3 )退出状态
$?
变量表示前一个命令的退出状态。
退出状态是每个命令在完成后返回的数值。通常,大多数命令在成功执行时返回退出状态 0,而在执行失败时返回 1。
一些命令会返回额外的退出状态以表示特定原因。例如,有些命令会区分不同类型的错误,并根据失败的具体类型返回不同的退出值。
下面是一个使用 $?
变量的示例分析,展示如何检查前一个命令的退出状态:
#!/bin/bash # 运行一个成功的命令 ls / > /dev/null echo "Exit status after ls: $?" # 运行一个失败的命令 ls /nonexistent_directory > /dev/null 2>&1 echo "Exit status after ls /nonexistent_directory: $?" # 运行一个成功的命令 echo "Hello, World!" > /dev/null echo "Exit status after echo: $?" # 运行一个失败的命令 cat non_existent_file > /dev/null 2>&1 echo "Exit status after cat non_existent_file: $?"
解释:
ls /
是一个成功的命令,列出根目录的内容。退出状态会是 0,因此$?
将返回 0。ls /nonexistent_directory
是一个失败的命令,因为该目录不存在。退出状态将是 2(具体值可能因不同的命令而异),因此$?
将返回 2。echo "Hello, World!"
是一个成功的命令,输出文本到标准输出。退出状态将是 0,因此$?
将返回 0。cat non_existent_file
是一个失败的命令,因为文件不存在。退出状态将是 1,表示发生了错误。
示例运行结果:
Exit status after ls: 0 Exit status after ls /nonexistent_directory: 2 Exit status after echo: 0 Exit status after cat non_existent_file: 1
这个示例展示了如何使用 $?
来检查和处理不同命令的退出状态,以便在脚本中做出适当的响应。
2.4 $! – 最后一个后台进程的进程 ID
以下是一个示例,演示如何使用 $!
变量来获取最后一个后台进程的进程 ID(PID):
#!/bin/bash # 启动一个后台进程 sleep 30 & # 获取最后一个后台进程的 PID BACKGROUND_PID=$! # 输出后台进程的 PID echo "The PID of the last background process is: $BACKGROUND_PID" # 等待后台进程完成 wait $BACKGROUND_PID # 输出后台进程完成后的消息 echo "The background process with PID $BACKGROUND_PID has completed."
解释:
sleep 30 &
启动一个后台进程,该进程会休眠 30 秒。&
符号用于将进程放到后台运行。BACKGROUND_PID=$!
将最后一个后台进程的 PID 存储在变量BACKGROUND_PID
中。$!
变量表示最后一个后台进程的 PID。echo "The PID of the last background process is: $BACKGROUND_PID"
输出后台进程的 PID。wait $BACKGROUND_PID
等待指定的后台进程完成。echo "The background process with PID $BACKGROUND_PID has completed."
输出后台进程完成后的消息。
运行
./script_name.sh
运行结果
The PID of the last background process is: 12345 The background process with PID 12345 has completed.
在这个示例中,$!
用于获取并存储最后一个后台进程的进程 ID,以便后续可以使用 wait
命令等待该进程完成。
2.5)总和命令行实例
以下脚本 script_name.sh 使用了与命令行相关的各种特殊变量 −
#!/bin/bash # 输出脚本名称 echo "Script name: $0" # 输出第一个、第二个和第三个参数 echo "First argument: $1" echo "Second argument: $2" echo "Third argument: $3" # 输出所有参数 echo "All arguments: $@" # 输出参数的数量 echo "Number of arguments: $#" # 显示当前 Shell 的进程 ID echo "Current Shell PID: $$" # 显示最后一个命令的退出状态 echo "Exit status of the last command: $?" # 显示最后一个后台命令的进程 ID echo "PID of the last background command: $!"
运行:
./script_name.sh arg1 arg2 arg3
运行结果:
Script name: ./script_name.sh First argument: arg1 Second argument: arg2 Third argument: arg3 All arguments: arg1 arg2 arg3 Number of arguments: 3 Current Shell PID: 12345 Exit status of the last command: 0 PID of the last background command: 6789
在这个示例中,脚本使用了多个特殊变量来输出脚本名称、传递的参数、参数的数量,以及其他相关信息。
结论:特殊字符的应用:
$0当前脚本的文件名
$n传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。
$#传递给脚本或函数的参数个数。
$*传递给脚本或函数的所有参数。
$@传递给脚本或函数的所有参数。被双引号(” “)包含时,与 $* 稍有不同。
$?上个命令的退出状态,或函数的返回值。
$$当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。