介绍
在本实验中,你将学习 Shell 脚本中的特殊变量。这些变量提供了关于脚本执行环境的关键信息,例如命令行参数、脚本名称和进程 ID。掌握这些变量将帮助你编写更加灵活且功能强大的 Shell 脚本。
创建你的第一个脚本
让我们从创建一个简单的 Shell 脚本开始,以此来演示特殊变量的使用。
在 WebIDE 中打开终端。你应该能看到一个等待输入的命令行提示符。
切换到项目目录:
cd ~/project
此命令将当前目录更改为 ~/project,这是你本实验的默认工作目录。
- 使用以下命令创建一个名为
special_vars.sh的新文件:
touch special_vars.sh
touch 命令会在文件不存在时创建一个空文件,如果文件已存在则更新其时间戳。
在 WebIDE 编辑器中打开该文件。你可以通过点击屏幕左侧文件浏览器中的文件名来完成此操作。
将以下内容添加到文件中:
#!/bin/bash
echo "Script Name: $0"
echo "First Argument: $1"
echo "Second Argument: $2"
echo "All Arguments: $@"
echo "Number of Arguments: $#"
echo "Process ID: $$"
让我们逐行解析每一项的作用:
#!/bin/bash:这被称为 Shebang。它告诉系统使用 bash 来解释执行此脚本。$0:这个特殊变量保存了脚本的名称。$1和$2:分别代表第一个和第二个命令行参数。$@:代表传递给脚本的所有命令行参数。$#:提供命令行参数的总数。$$:提供当前 Shell 的进程 ID(PID)。
添加内容后保存文件。
在终端运行以下命令,为脚本添加执行权限:
chmod +x special_vars.sh
chmod 命令用于更改文件权限。+x 选项增加了执行权限,允许你运行该脚本。
运行带参数的脚本
现在我们已经创建了脚本,让我们带上不同的参数来运行它,看看特殊变量是如何表现的。
- 在不带任何参数的情况下运行脚本:
./special_vars.sh
脚本名称前的 ./ 告诉 Shell 在当前目录中查找该脚本。
你应该会看到类似这样的输出:
Script Name: ./special_vars.sh
First Argument:
Second Argument:
All Arguments:
Number of Arguments: 0
Process ID: 1234
请注意,由于我们没有提供任何参数,第一个和第二个参数为空,且参数个数为 0。
- 现在,带上一些参数运行脚本:
./special_vars.sh hello world
输出应该如下所示:
Script Name: ./special_vars.sh
First Argument: hello
Second Argument: world
All Arguments: hello world
Number of Arguments: 2
Process ID: 1235
以下是发生的变化:
$1现在包含「hello」$2现在包含「world」$@显示了所有参数:「hello world」$#显示为 2,因为我们提供了两个参数
进程 ID($$)在每次运行脚本时可能会有所不同,因为它是由操作系统动态分配的。
理解 $? 和 $!
另外两个重要的特殊变量是 $? 和 $!。让我们创建一个新脚本来演示它们的用法。
- 创建一个名为
exit_status.sh的新文件:
touch ~/project/exit_status.sh
- 在 WebIDE 编辑器中打开该文件并添加以下内容:
#!/bin/bash
echo "Running a successful command:"
ls /home
echo "Exit status: $?"
echo "Running a command that will fail:"
ls /nonexistent_directory
echo "Exit status: $?"
echo "Running a background process:"
sleep 2 &
echo "Process ID of last background command: $!"
让我们解析一下这个脚本:
$?提供上一个执行命令的退出状态(Exit Status)。0 通常表示成功,而非零值则表示各种错误情况。$!提供上一个后台命令的进程 ID。- 命令末尾的
&符号使其在后台运行。
- 保存文件并添加执行权限:
chmod +x ~/project/exit_status.sh
- 运行脚本:
./exit_status.sh
你应该会看到类似这样的输出:
Running a successful command:
labex
Exit status: 0
Running a command that will fail:
ls: cannot access '/nonexistent_directory': No such file or directory
Exit status: 2
Running a background process:
Process ID of last background command: 1236
请注意:
- 第一个
ls命令执行成功,因此$?为 0。 - 第二个
ls命令失败(因为目录不存在),因此$?为 2(一个表示错误的非零值)。 sleep命令在后台运行,$!给出了它的进程 ID。
在函数中使用特殊变量
特殊变量也可以在函数内部使用。让我们创建一个脚本来演示这一点。
- 创建一个名为
function_vars.sh的新文件:
touch ~/project/function_vars.sh
- 在 WebIDE 编辑器中打开该文件并添加以下内容:
#!/bin/bash
function print_args {
echo "Function Name: $0"
echo "First Argument: $1"
echo "Second Argument: $2"
echo "All Arguments: $@"
echo "Number of Arguments: $#"
}
echo "Calling function with two arguments:"
print_args hello world
echo "Calling function with four arguments:"
print_args one two three four
这个脚本定义了一个使用特殊变量的函数 print_args。然后,它使用不同数量的参数两次调用该函数。
- 保存文件并添加执行权限:
chmod +x ~/project/function_vars.sh
- 运行脚本:
./function_vars.sh
你应该会看到类似这样的输出:
Calling function with two arguments:
Function Name: ./function_vars.sh
First Argument: hello
Second Argument: world
All Arguments: hello world
Number of Arguments: 2
Calling function with four arguments:
Function Name: ./function_vars.sh
First Argument: one
Second Argument: two
All Arguments: one two three four
Number of Arguments: 4
请注意:
$0仍然指向脚本名称,而不是函数名称。$1、$2、$@和$#在函数参数中的作用与在脚本参数中完全一致。- 每当使用不同参数调用函数时,这些变量的值都会随之改变。
理解 $@ 和 $* 的区别
特殊变量 $@ 和 $* 都用于表示所有命令行参数,但当它们被包含在双引号中时,行为会有所不同。让我们创建一个脚本来演示这种区别。
- 创建一个名为
at_vs_star.sh的新文件:
touch ~/project/at_vs_star.sh
- 在 WebIDE 编辑器中打开该文件并添加以下内容:
#!/bin/bash
echo "Using \$@:"
for arg in "$@"; do
echo "Argument: $arg"
done
echo "Using \$*:"
for arg in "$*"; do
echo "Argument: $arg"
done
这个脚本演示了在循环中使用 "$@" 和 "$*" 的区别。
- 保存文件并添加执行权限:
chmod +x ~/project/at_vs_star.sh
- 运行脚本并传入多个参数,包括一些带有空格的参数:
./at_vs_star.sh "arg with spaces" another_arg "third arg"
你应该会看到类似这样的输出:
Using $@:
Argument: arg with spaces
Argument: another_arg
Argument: third arg
Using $*:
Argument: arg with spaces another_arg third arg
以下是发生的情况:
- 使用
"$@"时,每个参数都被视为一个独立的实体。带有空格的参数会被保留为单个单元。 - 使用
"$*"时,所有参数都被合并成一个单一的字符串,由 IFS(内部字段分隔符)变量的第一个字符(通常是空格)分隔。
当你需要处理可能包含空格或其他特殊字符的参数时,这种区别至关重要。
总结
在本实验中,你学习了 Shell 脚本中的特殊变量以及如何有效地使用它们。你创建了多个脚本来演示各种特殊变量的用法,例如 $0、$1、$@、$#、$$、$? 和 $!。你还探索了这些变量在不同上下文中的表现,包括在函数内部以及处理命令行参数时。
关键要点:
$0、$1、$2等代表脚本名称和命令行参数。$@和$#允许你处理所有参数并统计其数量。$$提供了当前进程 ID,这在创建唯一的临时文件时非常有用。$?帮助你检查上一个命令是否执行成功。$!提供了上一个后台进程的 PID,在作业控制中非常有用。"$@"和"$*"在加引号时表现不同,这在处理带空格的参数时非常重要。
理解这些特殊变量对于编写更高级、更灵活的 Shell 脚本至关重要。它们允许你创建能够适应不同输入并提供执行环境重要信息的脚本。
随着你继续练习和尝试 Shell 脚本,你会发现更多在工作中使用这些特殊变量的方法。记得查阅 Bash 手册(man bash)以获取有关这些变量及其他特殊变量的更详细信息。



