Shell 位置参数
运行 Shell 脚本文件时我们可以给它传递一些参数,这些参数在脚本文件内部可以使用$n的形式来接收,例如,$1 表示第一个参数,$2 表示第二个参数,依次类推。
同样,在调用函数时也可以传递参数。Shell 函数参数的传递和其它编程语言不同,没有所谓的形参和实参,在定义函数时也不用指明参数的名字和数目。换句话说,定义 Shell 函数时不能带参数,但是在调用函数时却可以传递参数,这些传递进来的参数,在函数内部就也使用$n的形式接收,例如,$1 表示第一个参数,$2 表示第二个参数,依次类推。
这种通过$n的形式来接收的参数,在 Shell 中称为位置参数。
变量的名字必须以字母或者下划线开头,不能以数字开头;但是位置参数却偏偏是数字,这和变量的命名规则是相悖的,所以我们将它们视为“特殊变量”。
除了 $n,Shell 中还有 $#、$*、$@、$?、$$ 几个特殊参数
1) 给脚本文件传递位置参数
请编写下面的代码,并命名为 test.sh:
#!/bin/bashecho "Language: $1"echo "URL: $2"
运行 test.sh,并附带参数:
[yuanzi@localhost ~]$ cd demo
[yuanzi@localhost demo]$ . ./test.sh Shell https://www.yuque.com/
Language: Shell
URL: https://www.yuque.com/
其中Shell是第一个位置参数,https://www.yuque.com/是第二个位置参数,两者之间以空格分隔。
2) 给函数传递位置参数
请编写下面的代码,并命名为 test.sh:
#!/bin/bash#定义函数function func(){echo "Language: $1"echo "URL: $2"}#调用函数func C++ https://www.yuque.com/
运行 test.sh:
[yuanzi@localhost ~]$ cd demo
[yuanzi@localhost demo]$ . ./test.sh
Language: C++
URL: https://www.yuque.com/
注意事项 如果参数个数太多,达到或者超过了 10 个,那么就得用
${n}的形式来接收了,例如 ${10}、${23}。{ }的作用是为了帮助解释器识别参数的边界,这跟使用变量时加{ }是一样的效果
Shell特殊变量:Shell $#、$*、$@、$?、$$
Shell 特殊变量及其含义
| 变量 | 含义 |
|---|---|
| $0 | 当前脚本的文件名。 |
| $n(n≥1) | 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是 $1,第二个参数是 $2。 |
| $# | 传递给脚本或函数的参数个数。 |
| $* | 传递给脚本或函数的所有参数。 |
| $@ | 传递给脚本或函数的所有参数。当被双引号" "包含时,$@ 与 $* 稍有不同。 |
| $? | 上个命令的退出状态,或函数的返回值 |
| $$ | 当前 Shell 进程 ID。对于 Shell 脚本,就是这些脚本所在的进程 ID。 |
示例
1) 给脚本文件传递参数
编写下面的代码,并保存为 test.sh:
#!/bin/bashecho "Process ID: $$"echo "File Name: $0"echo "First Parameter : $1"echo "Second Parameter : $2"echo "All parameters 1: $@"echo "All parameters 2: $*"echo "Total: $#"
运行 test.sh,并附带参数:
2) 给函数传递参数**
编写下面的代码,并保存为 test.sh:
#!/bin/bash#定义函数function func(){echo "Language: $1"echo "URL: $2"echo "First Parameter : $1"echo "Second Parameter : $2"echo "All parameters 1: $@"echo "All parameters 2: $*"echo "Total: $#"}#调用函数func Java http://www.yuque.com/java/
运行结果为:
Shell $*和$@之间的区别
$ 和 $@ 都表示传递给函数或脚本的所有参数,
当 $ 和 $@ 不被双引号" "包围时,它们之间没有任何区别,都是将接收到的每个参数看做一份数据,彼此之间以空格来分隔。
但是当它们被双引号" "包含时,就会有区别了:
"$*"会将所有的参数从整体上看做一份数据,而不是把每个参数都看做一份数据。"$@"仍然将每个参数都看作一份数据,彼此之间是独立的。
比如传递了 5 个参数,那么对于"$*"来说,这 5 个参数会合并到一起形成一份数据,它们之间是无法分割的;而对于"$@"来说,这 5 个参数是相互独立的,它们是 5 份数据。
如果使用 echo 直接输出"$*"和"$@"做对比,是看不出区别的;但如果使用 for 循环来逐个输出数据,立即就能看出区别来。
编写下面的代码,并保存为 test.sh:
#!/bin/bashecho "print each param from \"\$*\""for var in "$*"doecho "$var"doneecho "print each param from \"\$@\""for var in "$@"doecho "$var"done
运行 test.sh,并附带参数:
从运行结果可以发现,
对于"$*",只循环了 1 次,因为它只有 1 分数据;
对于"$@",循环了 5 次,因为它有 5 份数据
Shell $?
$? 是一个特殊变量,用来获取上一个命令的退出状态,或者上一个函数的返回值。
所谓退出状态,就是上一个命令执行后的返回结果。退出状态是一个数字,一般情况下,大部分命令执行成功会返回 0,失败返回 1,这和C语言的 main() 函数是类似的。
不过,也有一些命令返回其他值,表示不同类型的错误。
1) $? 获取上一个命令的退出状态
编写下面的代码,并保存为 test.sh:
#!/bin/bashif [ "$1" == 100 ]thenexit 0 #参数正确,退出状态为0elseexit 1 #参数错误,退出状态1fi
exit表示退出当前 Shell 进程,我们必须在新进程中运行 test.sh,否则当前 Shell 会话(终端窗口)会被关闭,我们就无法取得它的退出状态了。
例如,运行 test.sh 时传递参数 100:
[yuanzi@localhost ~]$ cd demo[yuanzi@localhost demo]$ bash ./test.sh 100 #作为一个新进程运行[yuanzi@localhost demo]$ echo $?0# 再如,运行 test.sh 时传递参数 89:[yuanzi@localhost demo]$ bash ./test.sh 89 #作为一个新进程运行[yuanzi@localhost demo]$ echo $?1
2) $? 获取函数的返回值
编写下面的代码,并保存为 test.sh:
#!/bin/bash#得到两个数相加的和function add(){return `expr $1 + $2`}add 23 50 #调用函数echo $? #获取函数返回值
运行结果:
73
