一篇文章学会shell脚本
一、Shell传递参数
1 #!/bin/bash 2 3 # 假设在脚本运行时写了三个参数 1、2、3,,则 " * " 等价于 "1 2 3"(传递了一个参数),而 "@" 等价于 "1" "2" "3"(传递了三个参数)。 4 5 echo "-- \$* 演示 --" 6 for i in "$*"; do 7 echo $i 8 done 9 10 echo "-- \$@ 演示 --" 11 for i in "$@"; do 12 echo $i 13 done
运行:
$ sh shell.sh 1 2 3 -- $* 演示 -- 1 2 3 -- $@ 演示 -- 1 2 3
二、Shell数组
1 #!/bin/bash 2 my_array=(A B "C" D) 3 echo "第一个元素:${my_array[0]}" 4 echo "第二个元素:${my_array[1]}" 5 echo "第三个元素:${my_array[2]}" 6 echo "第四个元素:${my_array[3]}" 7 echo "数组的元素为:${my_array[*]}" # 获取数组中的所有元素 8 echo "数组的元素为:${my_array[@]}" # 获取数组中的所有元素 9 echo "数组元素个数为:${#my_array[*]}" # 获取数组的长度 10 echo "数组元素个数为:${#my_array[@]}" # 获取数组的长度
运行:
第一个元素:A 第二个元素:B 第三个元素:C 第四个元素:D 数组的元素为:A B C D 数组的元素为:A B C D 数组元素个数为:4 数组元素个数为:4
三、Shell运算符
1、算术运算符
1 #!/bin/bash 2 a=10 3 b=20 4 5 val=`expr $a + $b` 6 echo "a + b = $val" 7 8 val=`expr $a - $b` 9 echo "a - b = $val" 10 11 val=`expr $a \* $b` 12 echo "a * b = $val" 13 14 val=`expr $b / $a` 15 echo "b / a = $val" 16 17 val=`expr $b % $a` 18 echo "b % a = $val" 19 20 if [ $a == $b ] 21 then echo "a==b" 22 fi 23 24 if [ $a != $b ] 25 then echo "a!=b" 26 fi
注意:条件表达式要放在方括号之间,并且要有空格,例如: [$a==$b] 是错误的,必须写成 [ $a == $b ]。
- 乘号(*)前边必须加反斜杠(\)才能实现乘法运算;
运行:
a + b = 30 a - b = -10 a * b = 200 b / a = 2 b % a = 0 a!=b
2、关系运算符
1 #!/bin/bash 2 3 a=10 4 b=20 5 6 if [ $a -eq $b ] 7 then 8 echo "$a -eq $b : a 等于 b" 9 else 10 echo "$a -eq $b : a 不等于 b" 11 fi 12 13 if [ $a -ne $b ] 14 then 15 echo "$a -ne $b : a 不等于 b" 16 else 17 echo "$a -ne $b : a 等于 b" 18 fi 19 20 if [ $a -gt $b ] 21 then 22 echo "$a -gt $b: a 大于 b" 23 else 24 echo "$a -gt $b: a 不大于 b" 25 fi 26 27 if [ $a -lt $b ] 28 then 29 echo "$a -lt $b: a 小于 b" 30 else 31 echo "$a -lt $b: a 不小于 b" 32 fi 33 34 if [ $a -ge $b ] 35 then 36 echo "$a -ge $b: a 大于等于 b" 37 else 38 echo "$a -ge $b: a 小于 b" 39 fi 40 41 if [ $a -le $b ] 42 then 43 echo "$a -le $b: a 小于等于 b" 44 else 45 echo "$a -le $b: a 大于 b" 46 fi
运行:
10 -eq 20 : a 不等于 b 10 -ne 20 : a 不等于 b 10 -gt 20: a 不大于 b 10 -lt 20: a 小于 b 10 -ge 20: a 小于 b 10 -le 20: a 小于等于 b
3、布尔运算符
1 #!/bin/bash 2 3 a=10 4 b=20 5 6 if [ $a != $b ] 7 then 8 echo "$a != $b : a 不等于 b" 9 else 10 echo "$a == $b : a 等于 b" 11 fi 12 13 if [ $a -lt 100 -a $b -gt 15 ] 14 then 15 echo "$a 小于100 且 $b 大于 15 : 返回true" 16 else 17 echo "$a 小于100 且 $b 大于 15 : 返回false" 18 fi 19 if [ $a -lt 100 -o $b -gt 100 ] 20 then 21 echo "$a 小于 100 或 $b 大于 100 : 返回 true" 22 else 23 echo "$a 小于 100 或 $b 大于 100 : 返回 false" 24 fi 25 if [ $a -lt 5 -o $b -gt 100 ] 26 then 27 echo "$a 小于 5 或 $b 大于 100 : 返回 true" 28 else 29 echo "$a 小于 5 或 $b 大于 100 : 返回 false"
运行:
10 != 20 : a 不等于 b 10 小于100 且 20 大于 15 : 返回true 10 小于 100 或 20 大于 100 : 返回 true 10 小于 5 或 20 大于 100 : 返回 false
4、逻辑运算符
#!/bin/bash a=10 b=20 if [[ $a -lt 100 && $b -gt 100 ]] then echo "返回 true" else echo "返回 false" fi if [[ $a -lt 100 || $b -gt 100 ]] then echo "返回 true" else echo "返回 false" fi
运行:
返回 false 返回 true
5、字符串运算符
1 #!/bin/bash 2 3 a="abc" 4 b="efg" 5 6 if [ $a = $b ] 7 then 8 echo "$a = $b : a 等于 b" 9 else 10 echo "$a = $b: a 不等于 b" 11 fi 12 if [ $a != $b ] 13 then 14 echo "$a != $b : a 不等于 b" 15 else 16 echo "$a != $b: a 等于 b" 17 fi 18 if [ -z $a ] 19 then 20 echo "-z $a : 字符串长度为 0" 21 else 22 echo "-z $a : 字符串长度不为 0" 23 fi 24 if [ -n "$a" ] 25 then 26 echo "-n $a : 字符串长度不为 0" 27 else 28 echo "-n $a : 字符串长度为 0" 29 fi 30 if [ $a ] 31 then 32 echo "$a : 字符串不为空" 33 else 34 echo "$a : 字符串为空" 35 fi
运行:
abc = efg: a 不等于 b abc != efg : a 不等于 b -z abc : 字符串长度不为 0 -n abc : 字符串长度不为 0 abc : 字符串不为空
6、文件测试运算符
1 #!/bin/bash 2 3 file="/doc/shell-operator.sh" 4 if [ -r $file ] 5 then 6 echo "文件可读" 7 else 8 echo "文件不可读" 9 fi 10 11 if [ -w $file ] 12 then 13 echo "文件可写" 14 else 15 echo "文件不可写" 16 fi 17 18 if [ -x $file ] 19 then 20 echo "文件可执行" 21 else 22 echo "文件不可执行" 23 fi 24 25 if [ -f $file ] 26 then 27 echo "文件为普通文件" 28 else 29 echo "文件为特殊文件" 30 fi 31 32 if [ -d $file ] 33 then 34 echo "文件为目录" 35 else 36 echo "文件为非目录" 37 fi 38 39 if [ -s $file ] 40 then 41 echo "文件不为空" 42 else 43 echo "文件为空" 44 fi 45 46 if [ -e $file ] 47 then 48 echo "文件存在" 49 else 50 echo "文件不存在" 51 fi
运行:
文件可读
文件可写
文件不可执行
文件为普通文件
文件为非目录
文件不为空
文件存在
四、Shell echo
1 #!/bin/bash 2 3 echo "\"It is a test\"" # 显示转义字符 4 5 echo -e "OK! \n" # -e 开启转义 6 echo "It is a test" 7 8 #!/bin/sh 9 echo -e "OK! \c" # -e 开启转义 \c 不换行 10 echo "It is a test" 11 12 echo '$name\"' # 原样输出字符串,不进行转义或取变量(用单引号) 13 14 echo `date` # 显示命令执行结果
运行:
"It is a test" -e OK! It is a test -e OK! It is a test $name\" 2019年 7月24日 星期三 21时01分00秒 CST
五、Shell printf
1 #!/bin/bash 2 3 # %-10s 指一个宽度为10个字符(-表示左对齐,没有则表示右对齐),任何字符都会被显示在10个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。 4 # %-4.2f 指格式化为小数,其中.2指保留2位小数。 5 printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg 6 printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234 7 printf "%-10s %-8s %-4.2f\n" 杨过 男 48.6543 8 printf "%-10s %-8s %-4.2f\n" 郭芙 女 47.9876 9 10 11 # format-string为双引号 12 printf "%d %s\n" 1 "abc" 13 14 # 单引号与双引号效果一样 15 printf '%d %s\n' 1 "abc" 16 17 # 没有引号也可以输出 18 printf %s abcdef 19 20 # 格式只指定了一个参数,但多出的参数仍然会按照该格式输出,format-string 被重用 21 printf %s abc def 22 23 printf "%s\n" abc def 24 25 printf "%s %s %s\n" a b c d e f g h i j 26 27 # 如果没有 arguments,那么 %s 用NULL代替,%d 用 0 代替 28 printf "%s and %d \n"
运行:
姓名 性别 体重kg 郭靖 男 66.12 杨过 男 48.65 郭芙 女 47.99 1 abc 1 abc abcdefabcdefabc def a b c d e f g h i j and 0
六、Shell test
1 #!/bin/bash 2 3 num1=100 4 num2=100 5 if test $[num1] -eq $[num2] 6 then 7 echo "两个数相等" 8 else 9 echo "两个数不相等" 10 fi 11 12 a=5 13 b=6 14 15 result=$[a+b] # 代码中的 [] 执行基本的算数运算 16 echo "result为:$result" 17 18 num1="ru1noob" 19 num2="runoob" 20 if test $num1 = $num2 21 then 22 echo '两个字符串相等!' 23 else 24 echo '两个字符串不相等!' 25 fi
运行:
两个数相等 result为:11 两个字符串不相等!
七、Shell 流程控制
1 #!/bin/bash 2 3 # if else 4 5 a=10 6 b=20 7 if [ $a == $b ] 8 then 9 echo "a 等于 b" 10 elif [ $a -gt $b ] 11 then 12 echo "a 大于 b" 13 elif [ $a -lt $b ] 14 then 15 echo "a 小于 b" 16 else 17 echo "没有符合的条件" 18 fi 19 20 # for 循环 21 for loop in 1 2 3 4 5 22 do 23 echo "The value is: $loop" 24 done 25 26 27 # while语句 28 # 以下是一个基本的while循环,测试条件是:如果int小于等于5,那么条件返回真。int从0开始,每次循环处理时,int加1。运行上述脚本,返回数字1到5,然后终止。 29 int=1 30 while(( $int<=5 )) 31 do 32 echo $int 33 let "int++" # 使用中使用了 Bash let 命令,它用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量 34 done
运行:
a 小于 b The value is: 1 The value is: 2 The value is: 3 The value is: 4 The value is: 5 1 2 3 4 5
八、函数
1 #!/bin/bash 2 3 # 最简单的函数及调用 4 demoFun(){ 5 echo "这是我的第一个 shell 函数!" 6 } 7 echo "-----函数开始执行-----" 8 demoFun 9 echo "-----函数执行完毕-----" 10 11 # 带return的函数 12 funWithReturn(){ 13 echo "这个函数会对输入的两个数字进行相加运算..." 14 echo "输入第一个数字: " 15 read aNum 16 echo "输入第二个数字: " 17 read anotherNum 18 echo "两个数字分别为 $aNum 和 $anotherNum !" 19 return $(($aNum+$anotherNum)) 20 } 21 funWithReturn 22 echo "输入的两个数字之和为 $? !" 23 24 # 带参数的函数 25 funWithParam(){ 26 echo "第一个参数为 $1 !" 27 echo "第二个参数为 $2 !" 28 echo "第十个参数为 $10 !" # 注意,$10 不能获取第十个参数,获取第十个参数需要${10}。当n>=10时,需要使用${n}来获取参数。 29 echo "第十个参数为 ${10} !" 30 echo "第十一个参数为 ${11} !" 31 echo "参数总数有 $# 个!" 32 echo "作为一个字符串输出所有参数 $* !" 33 } 34 funWithParam 1 2 3 4 5 6 7 8 9 34 73
运行:
-----函数开始执行----- 这是我的第一个 shell 函数! -----函数执行完毕----- 这个函数会对输入的两个数字进行相加运算... 输入第一个数字: 10 输入第二个数字: 20 两个数字分别为 10 和 20 ! 输入的两个数字之和为 30 ! 第一个参数为 1 ! 第二个参数为 2 ! 第十个参数为 10 ! 第十个参数为 34 ! 第十一个参数为 73 ! 参数总数有 11 个! 作为一个字符串输出所有参数 1 2 3 4 5 6 7 8 9 34 73 !
九、输入、输出重定向
命令 | 说明 |
---|---|
command > file | 将输出重定向到 file。 |
command < file | 将输入重定向到 file。 |
command >> file | 将输出以追加的方式重定向到 file。 |
n > file | 将文件描述符为 n 的文件重定向到 file。 |
n >> file | 将文件描述符为 n 的文件以追加的方式重定向到 file。 |
n >& m | 将输出文件 m 和 n 合并。 |
n <& m | 将输入文件 m 和 n 合并。 |
<< tag | 将开始标记 tag 和结束标记 tag 之间的内容作为输入。 |
首先新建users文件
$ cat users _mbsetupuser console Oct 31 17:35 user console Oct 31 17:35 user2 console Dec 1 11:33
1、输出重定向
输出重定向会覆盖文件内容:
$ echo "测试输出重定向" > users $ cat users 测试输出重定向 $
如果不希望文件内容被覆盖,可以使用 >> 追加到文件末尾:
$ echo "测试输出重定向" >> users $ cat users 测试输出重定向 测试输出重定向 $
2、输入重定向
现需要统计 users 文件的行数,执行以下命令:
$ wc -l users 2 users
将输入重定向到 users 文件:
$ wc -l < users 2
注意:结果不同原因:第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容。
3、/dev/null 文件
如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:
$ command > /dev/null
/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。
十、文件包含
语法:
. filename # 注意点号(.)和文件名中间有一空格
或
source filename
使用 . 或者 source来包含文件即可。