-
Shell 传递参数
我们可以在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为 $n,n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数。
例如可以使用 $1、$2 等来引用传递给脚本的参数,其中 $1 表示第一个参数,$2 表示第二个参数,依此类推。
另外,还有几个特殊字符用来处理参数:
参数处理 说明 $# 传递到脚本的参数个数 $* 以一个单字符串显示所有向脚本传递的参数。 如"$*“用「”」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。 $$ 脚本运行的当前进程ID号 $! 后台运行的最后一个进程的ID号 $@ 与 ∗ 相同,但是使用时加引号,并在引号中返回每个参数。如 " *相同,但是使用时加引号,并在引号中返回每个参数。 如" ∗相同,但是使用时加引号,并在引号中返回每个参数。如"@“用「”」括起来的情况、以"$1" “ 2 " … " 2" … " 2"…"n” 的形式输出所有参数。 $- 显示Shell使用的当前选项,与set命令功能相同。 $? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。 测试脚本
#!/bin/bash # author:zhengnanecho "param trans success!"; echo "first param is $1"; echo "third param is $3"; echo "param list is $*"; echo "param number is $#"; for param in "$@"; doecho $param done; echo "current process id is $$"; # 运行结果 root@hcss-ecs-c2b8:/var/test# vim param_trans.sh root@hcss-ecs-c2b8:/var/test# chmod +x ./param_trans.sh root@hcss-ecs-c2b8:/var/test# ./param_trans.sh param1 param2 param3 param4 param trans success! first param is param1 third param is param3 param list is param1 param2 param3 param4 param number is 4 param1 param2 param3 param4 current process id is 18991
$* 与 $@ 区别:
- 相同点:都是引用所有参数。
- 不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数 1、2、3,则 " * " 等价于 “1 2 3”(传递了一个参数),而 “@” 等价于 “1” “2” “3”(传递了三个参数)。
思考:参数的传递提供了跟家灵活的脚本使用方式
-
Shell 基本运算符
Shell 和其他编程语言一样,支持多种运算符,包括:
- 算数运算符
- 关系运算符
- 布尔运算符
- 字符串运算符
- 文件测试运算符
原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。
expr 是一款表达式计算工具,使用它能完成表达式的求值操作。
例如,两个数相加(注意使用的是反引号 *`* 而不是单引号 *'*):
效果如下
*#!/bin/bash*val=`expr 2 + 2` echo "两数之和为 : $val" 执行脚本,输出结果如下所示: 两数之和为 : 4
两点注意:
-
表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。
-
完整的表达式要被
root@hcss-ecs-c2b8:/var/test# a=10 root@hcss-ecs-c2b8:/var/test# b=20 # 我们这里没有在运算符前后空格导致bash将其识别为字符拼接了 root@hcss-ecs-c2b8:/var/test# echo `expr $a-$b` 10-20 # 正确做法 root@hcss-ecs-c2b8:/var/test# echo `expr $a - $b` -10
-
算术运算符
root@hcss-ecs-c2b8:/var/test# a=10 root@hcss-ecs-c2b8:/var/test# b=20 root@hcss-ecs-c2b8:/var/test# echo `expr $b * $a` expr: syntax error: unexpected argument ‘hello.sh’root@hcss-ecs-c2b8:/var/test# echo `expr $b * $a` expr: syntax error: unexpected argument ‘hello.sh’root@hcss-ecs-c2b8:/var/test# echo `expr $b * $a` expr: syntax error: unexpected argument ‘hello.sh’ # 乘号(*)前边必须加反斜杠(\)才能实现乘法运算; root@hcss-ecs-c2b8:/var/test# echo `expr $b \* $a` 200 # 除法 root@hcss-ecs-c2b8:/var/test# echo `expr $b / $a` 2 # 是否相等 root@hcss-ecs-c2b8:/var/test# echo `expr $b == $a` 0 # 是否不相等 root@hcss-ecs-c2b8:/var/test# echo `expr $b != $a` 1
-
关系运算符
关系运算符只支持数字,不支持字符串,除非字符串的值是数字。
运算符 说明 举例 -eq 检测两个数是否相等,相等返回 true。 [ $a -eq $b ] 返回 false。 -ne 检测两个数是否不相等,不相等返回 true。 [ $a -ne $b ] 返回 true。 -gt 检测左边的数是否大于右边的,如果是,则返回 true。 [ $a -gt $b ] 返回 false。 -lt 检测左边的数是否小于右边的,如果是,则返回 true。 [ $a -lt $b ] 返回 true。 -ge 检测左边的数是否大于等于右边的,如果是,则返回 true。 [ $a -ge $b ] 返回 false。 -le 检测左边的数是否小于等于右边的,如果是,则返回 true。 [ $a -le $b ] 返回 true。 -
布尔运算符
运算符 说明 举例 ! 非运算,表达式为 true 则返回 false,否则返回 true。 [ ! false ] 返回 true。 -o 或运算(or),有一个表达式为 true 则返回 true。 [ $a -lt 20 -o $b -gt 100 ] 返回 true。 -a 与运算(and),两个表达式都为 true 才返回 true。 [ $a -lt 20 -a $b -gt 100 ] 返回 false。 用法和其他编程语言一样,这里就不在介绍
-
逻辑运算符
以下介绍 Shell 的逻辑运算符,假定变量 a 为 10,变量 b 为 20:
运算符 说明 举例 && 逻辑的 AND [[ $a -lt 100 && $b -gt 100 ]] 返回 false || 逻辑的 OR [[ $a -lt 100 || $b -gt 100 ]] 返回 true -
自增和自减操作符
尽管 Shell 本身没有像 C、C++ 或 Java 那样的 ++ 和 – 操作符,但可以通过其他方式实现相同的功能。以下是一些常见的方法:
使用 let 命令允许对整数进行算术运算。
root@hcss-ecs-c2b8:/var/test# num=10 root@hcss-ecs-c2b8:/var/test# let num++ root@hcss-ecs-c2b8:/var/test# echo $num 11 root@hcss-ecs-c2b8:/var/test# let num-- root@hcss-ecs-c2b8:/var/test# echo $num 10 root@hcss-ecs-c2b8:/var/test# let num-- root@hcss-ecs-c2b8:/var/test# echo $num 9 root@hcss-ecs-c2b8:/var/test#
-
文件测试运算符
文件测试运算符用于检测 Unix 文件的各种属性。
属性检测描述如下:
操作符 说明 举例 -b file 检测文件是否是块设备文件,如果是,则返回 true。 [ -b $file ] 返回 false。 -c file 检测文件是否是字符设备文件,如果是,则返回 true。 [ -c $file ] 返回 false。 -d file 检测文件是否是目录,如果是,则返回 true。 [ -d $file ] 返回 false。 -f file 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 [ -f $file ] 返回 true。 -g file 检测文件是否设置了 SGID 位,如果是,则返回 true。 [ -g $file ] 返回 false。 -k file 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 [ -k $file ] 返回 false。 -p file 检测文件是否是有名管道,如果是,则返回 true。 [ -p $file ] 返回 false。 -u file 检测文件是否设置了 SUID 位,如果是,则返回 true。 [ -u $file ] 返回 false。 -r file 检测文件是否可读,如果是,则返回 true。 [ -r $file ] 返回 true。 -w file 检测文件是否可写,如果是,则返回 true。 [ -w $file ] 返回 true。 -x file 检测文件是否可执行,如果是,则返回 true。 [ -x $file ] 返回 true。 -s file 检测文件是否为空(文件大小是否大于0),不为空返回 true。 [ -s $file ] 返回 true。 -e file 检测文件(包括目录)是否存在,如果是,则返回 true。 [ -e $file ] 返回 true。 其他检查符:
- -S: 判断某文件是否 socket。
- -L: 检测文件是否存在并且是一个符号链接。
思考:最常用的莫过于这5个(-f -e,-r,-w-x),当我们需要对某个文件操作的时候我们首先要判断是否为空文件,在判断是否可以读写和执行
简单编写一个文件移动的shell 脚本
#!/bin/bash# 检查参数数量 if [ "$#" -ne 2 ]; thenecho "用法: $0 <源文件> <目标目录>"exit 1 fifile="$1" dir="$2"# 检查源文件是否存在 if [ ! -f "$file" ]; thenecho "错误: 源文件 '$file' 不存在。"exit 1 fi# 检查目标目录是否存在 if [ ! -d "$fir" ]; thenecho "错误: 目标目录 '$dir' 不存在。"exit 1 fi# 移动文件 mv "$file" "$dir"echo "文件 '$file' 已成功移动到 '$dir'。"
root@hcss-ecs-c2b8:/var/test# vim file_move.sh root@hcss-ecs-c2b8:/var/test# vim file_move.sh # 执行脚本 # 但是报错说目录不存在仔细一看,脚本中变量名写错了,上述脚本代码中dir写错了fir,修改后就没有问题了 root@hcss-ecs-c2b8:/var/test# ./file_move.sh helloworld.sh dir1 错误: 目标目录 'dir1' 不存在。 root@hcss-ecs-c2b8:/var/test# ll total 20 drwxr-xr-x 3 root root 4096 Sep 22 10:01 ./ drwxr-xr-x 14 root root 4096 Sep 21 08:28 ../ drwxr-xr-x 2 root root 4096 Sep 22 09:58 dir1/ -rwxr-xr-x 1 root root 473 Sep 22 10:01 file_move.sh* ---x--x--x 1 root root 32 Sep 21 08:52 helloworld.sh* root@hcss-ecs-c2b8:/var/test# vim file_move.sh
# 用vim修改一下上述问题在执行就没有问题了 root@hcss-ecs-c2b8:/var/test# vim file_move.sh root@hcss-ecs-c2b8:/var/test# ./file_move.sh helloworld.sh dir1 文件 'helloworld.sh' 已成功移动到 'dir1'。