shell编程
- 1.
Shell
是一个用 C 语言编写的程序,它是用户使用Linux
的桥梁,包裹在Linux
内核的外面,为用户和内核之间的交换提供一个接口- 2.
Shell
也是一种解释器,用户的命令都交给Shell
解释执行- 3.
Shell
脚本(shell script
)是一种为Shell
编写的脚本程序,可以在Shell
上解释运行- 4.
Shell
的种类(常用):
- 1.
Bourne Shell(/usr/bin/sh或/bin/sh)
- 2.
Bourne Again Shell(/bin/bash)
1.shell 脚本程序
- 1.
shell
脚本的第一句需要指定它的解释器#!/bin/bash(默认解释器)
- 1.
#!
告诉系统其后路径所指定的程序即是解释此脚本文件的 Shell 程序- 2.
#!/bin/bash
也可以修改为#!/bin/sh
- 3.不指定也可以执行(默认采用
/bin/bash
)- 2.shell脚本的第二句可以写注释行
#说明程序的功能,开发者,开发时间等
- 3.shell脚本的程序体
#顺序结构 #分支结构(注意结束符,then等) if..then..else...fi if...then...elif...then...else...fi case...esac #循环结构 while... for... until...
2.启动shell程序的方式
- 1.通过
./shell脚本
运行(需要先使用chmod命令把文件的权限设置成可读,可执行)
- 2.通过
bash/sh shell脚本
运行
- 3.通过
bash < shell脚本
运行
- 4.通过
source shell脚本
运行
3.shell 变量
1.环境变量
shell
预定义变量,用于设置系统运行环境,该变量都是大写(例:PATH
)
2.位置变量
命令 参数1 参数2 ...
$0
表示第0个位置对应的变量
3.普通变量**
- 1.命名只能使用英文字母,数字和下划线,首个字符不能以数字开头
- 2.变量名中间不能有空格,可以使用下划线
_
- 3.不能使用标点符号
- 4.不能使用
bash
里的关键字(可用help
命令查看保留关键字)- 5.无类型,可以直接赋值
- 6.有
read
和=
两种赋值方式(其中=
两边不能有空格,read
可以同时给多个变量赋值,enter
键结束)- 7.对该变量引用:
$ 变量名/序号
或$ {变量名/序号}
,后者一般用于对数组元素的引用- 8.变量名外面的花括号是可选的,花括号是为了帮助解释器识别变量的边界
your_name="tom" echo $your_name your_name="alibaba" echo $your_name
4.数组变量(一维)
- 1.
数组变量名=(元素1 元素2 元素3...)
;例:Users=(Zsan lisi wangwu)
- 2.输出指定下标数组元素:
echo ${ Users[0/1/2...] }
- 3.输出数组中的全部元素:
echo $ {Users[*] }
- 4.输出数组的长度:
echo $ { #Users[*]}
- 5.数组赋值:
新的数组变量名=("${旧数组变量名[*]}")
,只能把旧数组的指定元素赋值给新数组的第一个元素
5.只读变量
- 使用
readonly
命令可以将变量定义为只读变量,只读变量的值不能被改变#!/bin/bash myUrl="https://www.google.com" readonly myUrl myUrl="https://www.runoob.com"
- 运行脚本,结果:
/bin/sh: NAME: This variable is read only.
6.特殊变量
- 1.
bash
:自动定义和赋值,用户不能改变- 2.
$$
:表示当前进程号- 3.
$?
:表示前一个命令的退出状态- 4.
$#
:表示命令的参数个数- 5.
$0
:表示命令本身- 6.
$ 1~$ n
:表示命令参数- 7.
$*
:表示全部命令参数
7.删除变量
- 使用
unset
命令可以删除变量unset variable_name
- 变量被删除后不能再次使用,
unset
命令不能删除只读变量
4.shell 字符串
- 字符串可以用单引号,也可以用双引号,也可以不用引号
1.单引号
str='this is a string'
- 1.单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的
- 2.单引号字串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用
2.双引号
your_name="runoob" str="Hello, I know you are \"$your_name\"! \n" echo -e $str
- 1.结果:
Hello, I know you are "runoob"!
- 2.双引号里可以有变量
- 3.双引号里可以出现转义字符
3.拼接字符串
your_name="runoob" # 使用双引号拼接 greeting="hello, "$your_name" !" greeting_1="hello, ${your_name} !" echo $greeting $greeting_1 # 使用单引号拼接 greeting_2='hello, '$your_name' !' greeting_3='hello, ${your_name} !' echo $greeting_2 $greeting_3
- 1.结果
hello, runoob ! hello, runoob !
hello, runoob ! hello, ${your_name} !
4.获取字符串长度
string="abcd" echo ${#string} # 输出 4 # 变量为数组时,${#string} 等价于 ${#string[0]}: string="abcd" echo ${#string[0]} # 输出 4
5.提取子字符串
# 从字符串第 2 个字符开始截取 4 个字符: string="runoob is a great site" echo ${string:1:4} # 输出 unoo,第一个字符的索引值为 0
6.查找子字符串
# 查找字符 i 或 o 的位置(哪个字母先出现就计算哪个) # 脚本中 ` 是反引号,而不是单引号 ' string="runoob is a great site" echo `expr index "$string" io` # 输出 4
5.shell 变量的输出
- 1.
echo $变量名1 $变量名2
,注意对变量的引用主要使用$,且自动添加换行符- 2.
printf 格式 变量
,不会自动添加换行符\n
1.echo 命令
1.显示普通字符串
echo "It is a test" 双引号可省略 echo It is a test
2.显示转义字符
echo "\"It is a test\"" 双引号可省略
3.显示变量
- read 命令从标准输入中读取一行,并把输入行的每个字段的值指定给 shell 变量
#!/bin/sh read name echo "$name It is a test"
[root@www ~]# sh test.sh OK #标准输入 OK It is a test #输出
4.显示换行
echo -e "OK! \n" # -e 开启转义 echo "It is a test"
OK! It is a test
5.显示不换行
#!/bin/sh echo -e "OK! \c" # -e 开启转义 \c 不换行 echo "It is a test"
OK! It is a test
6.显示结果定向至文件
echo "It is a test" > myfile
7.原样输出字符串,不进行转义或取变量(用单引号)
echo '$name\"'
$name\"
8.显示命令执行结果
echo `date` 注意: 这里使用的是反引号 `, 而不是单引号 '
Thu Jul 24 10:08:46 CST 2014
2.printf 命令
转义字符 说明 \a 警告字符,通常为ASCII的BEL字符 \b 后退 \c 抑制(不显示)输出结果中任何结尾的换行字符(只在%b格式指示符控制下的参数字符串中有效),而且,任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符,都被忽略 \f 换页(formfeed) \n 换行 \r 回车(Carriage return) \t 水平制表符 \v 垂直制表符 \ 一个字面上的反斜杠字符 \ddd 表示1到3位数八进制值的字符。仅在格式字符串中有效 \0ddd 表示1到3位的八进制值字符 printf format-string [arguments...]
format-string
: 为格式控制字符串arguments
: 为参数列表#!/bin/bash printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234 printf "%-10s %-8s %-4.2f\n" 杨过 男 48.6543 printf "%-10s %-8s %-4.2f\n" 郭芙 女 47.9876
姓名 性别 体重kg 郭靖 男 66.12 杨过 男 48.65 郭芙 女 47.99
- 1.
%s %c %d %f
都是格式替代符- 2.
%s
输出一个字符串- 3.
%d
整型输出- 4.
%c
输出一个字符- 5.
%f
输出实数,以小数形式输出- 6.
%-10s
指一个宽度为 10 个字符(- 表示左对齐,没有则表示右对齐),任何字符都会被显示在 10 个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来- 7.
%-4.2f
指格式化为小数,其中 .2 指保留2位小数#!/bin/bash # author:菜鸟教程 # url:www.runoob.com # format-string为双引号 printf "%d %s\n" 1 "abc" # 单引号与双引号效果一样 printf '%d %s\n' 1 "abc" # 没有引号也可以输出 printf %s abcdef # 格式只指定了一个参数,但多出的参数仍然会按照该格式输出,format-string 被重用 printf %s abc def printf "%s\n" abc def printf "%s %s %s\n" a b c d e f g h i j # 如果没有 arguments,那么 %s 用空字符串代替,%d 用 0 代替 printf "%s and %d \n"
1 abc 1 abc abcdefabcdefabc def a b c d e f g h i j and 0
$ printf "a string, no processing:<%s>\n" "A\nB" a string, no processing:<A\nB> $ printf "a string, no processing:<%b>\n" "A\nB" a string, no processing:<A B> $ printf "www.runoob.com \a" www.runoob.com $ #不换行
3.test 命令
- 1.
shell
中的test
命令用于检查某个条件是否成立- 2.它可以进行数值、字符和文件三个方面的测试
- 3.代码中的
[]
执行基本的算数运算- 4.
test
相当于中括号[]
,可以互换,但是[]与内容需要用空格隔开
1.数值测试
参数 说明 -eq 等于则为真 -ne 不等于则为真 -gt 大于则为真 -ge 大于等于则为真 -lt 小于则为真 -le 小于等于则为真 num1=100 num2=100 if test $[num1] -eq $[num2] then echo '两个数相等!' else echo '两个数不相等!' fi result=$[num1+num2] # 注意等号两边不能有空格 echo "result 为: $result"
2.字符串测试
参数 说明 = 等于则为真 != 不相等则为真 -z 字符串 字符串的长度为零则为真 -n 字符串 字符串的长度不为零则为真 num1="ru1noob" num2="runoob" if test $num1 = $num2 then echo '两个字符串相等!' else echo '两个字符串不相等!' fi
3.文件测试
参数 说明 -e 文件名 如果文件存在则为真 -r 文件名 如果文件存在且可读则为真 -w 文件名 如果文件存在且可写则为真 -x 文件名 如果文件存在且可执行则为真 -s 文件名 如果文件存在且至少有一个字符则为真 -d 文件名 如果文件存在且为目录则为真 -f 文件名 如果文件存在且为普通文件则为真 -c 文件名 如果文件存在且为字符型特殊文件则为真 -b 文件名 如果文件存在且为块特殊文件则为真
- shell 还提供了与( -a )、或( -o )、非( ! )三个逻辑操作符用于将测试条件连接起来
- 其优先级为: ! 最高, -a 次之, -o 最低
cd /bin if test -e ./notFile -o -e ./bash then echo '至少有一个文件存在!' else echo '两个文件都不存在' fi
6.shell 数组
- 1.
bash
支持一维数组(不支持多维数组),并且没有限定数组的大小(初始化时不需要定义数组大小)- 2.数组元素的下标由 0 开始。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于 0
1.定义数组
- 1.
shell
中用括号来表示数组,数组元素用空格符号分割开- 2.可以单独定义数组的每一个元素
- 3.可以不使用连续的下标,而且下标的范围没有限制
数组名=(值1 值2 ... 值n) 例: my_array=(A B "C" D) 或 array_name=( value0 value1 value2 value3 ) 或 array_name[0]=value0 array_name[1]=value1 。。。 array_name[n]=valuen
2.读取数组
${数组名[下标]} 例: valuen=${array_name[n]} 使用 @ 符号可以获取数组中的所有元素 例: echo ${array_name[@]}
#!/bin/bash my_array=(A B "C" D) echo "第一个元素为: ${my_array[0]}" echo "第二个元素为: ${my_array[1]}" echo "第三个元素为: ${my_array[2]}" echo "第四个元素为: ${my_array[3]}"
$ chmod +x test.sh $ ./test.sh 第一个元素为: A 第二个元素为: B 第三个元素为: C 第四个元素为: D
3.获取数组的长度
# 取得数组元素的个数 length=${#array_name[@]} # 或者 length=${#array_name[*]} # 取得数组单个元素的长度 lengthn=${#array_name[n]}
4.获取数组中的所有键/元素
#!/bin/bash my_array[0]=A my_array[1]=B my_array[2]=C my_array[3]=D echo "数组的元素为: ${my_array[*]}" echo "数组的元素为: ${my_array[@]}"
$ chmod +x test.sh $ ./test.sh 数组的元素为: A B C D 数组的元素为: A B C D
- 数组前加一个感叹号
!
可以获取数组的所有键declare -A site site["google"]="www.google.com" site["runoob"]="www.runoob.com" site["taobao"]="www.taobao.com" echo "数组的键为: ${!site[*]}" echo "数组的键为: ${!site[@]}"
数组的键为: google runoob taobao 数组的键为: google runoob taobao
5.关联数组
- 1.Bash 支持关联数组,可以使用任意的字符串、或者整数作为下标来访问数组元素
- 2.关联数组使用 declare 命令来声明
- 3.-A 选项用于声明一个关联数组
- 4.关联数组的键是唯一的
declare -A site=(["google"]="www.google.com" ["runoob"]="www.runoob.com" ["taobao"]="www.taobao.com") 或 declare -A site site["google"]="www.google.com" site["runoob"]="www.runoob.com" site["taobao"]="www.taobao.com" 通过键来访问关联数组的元素 echo ${site["runoob"]} www.runoob.com
7.shell 注释
1.单行注释
- 1.以
#
开头的行就是注释,会被解释器忽略- 2.通过每一行加一个
#
号设置多行注释- 3.注释的代码用一对花括号括起来,定义成一个函数,没有地方调用这个函数,这块代码就不会执行,达到了和注释一样的效果
#-------------------------------------------- # 这是一个注释 # author:菜鸟教程 # site:www.runoob.com # slogan:学的不仅是技术,更是梦想! #-------------------------------------------- ##### 用户配置区 开始 ##### # # # 这里可以添加脚本描述信息 # # ##### 用户配置区 结束 #####
2.多行注释
:<<EOF 注释内容... 注释内容... 注释内容... EOF 或 :<<' 注释内容... 注释内容... 注释内容... ' 或 :<<! 注释内容... 注释内容... 注释内容... !
8.shell 传递参数
- 1.执行
shell
脚本时,可以向脚本传递参数- 2.脚本内获取参数的格式为:
$n
- 3.
n
代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推……- 4.
$0
为执行的文件名(包含文件路径)#!/bin/bash echo "shell 传递参数实例!"; echo "执行的文件名:$0"; echo "第一个参数为:$1"; echo "第二个参数为:$2"; echo "第三个参数为:$3";
$ chmod +x test.sh $ ./test.sh 1 2 3 shell 传递参数实例! 执行的文件名:./test.sh 第一个参数为:1 第二个参数为:2 第三个参数为:3
注意
$#
:传递到脚本的参数个数$*
: 以一个单字符串显示所有向脚本传递的参数$$
:脚本运行的当前进程ID号$!
: 后台运行的最后一个进程的ID号$@
:与$*相同,但是使用时加引号,并在引号中返回每个参数$-
:显示shell使用的当前选项,与set命令功能相同$?
:显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误#!/bin/bash echo "Shell 传递参数实例!"; echo "第一个参数为:$1"; echo "参数个数为:$#"; echo "传递的参数作为一个字符串显示:$*";
$ chmod +x test.sh $ ./test.sh 1 2 3 Shell 传递参数实例! 第一个参数为:1 参数个数为:3 传递的参数作为一个字符串显示:1 2 3
$*
与$@
区别:- 相同点:都是引用所有参数。
- 不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数 1、2、3,,则 " * " 等价于 “1 2 3”(传递了一个参数),而 “@” 等价于 “1” “2” “3”(传递了三个参数)
#!/bin/bash echo "-- \$* 演示 ---" for i in "$*"; do echo $i done echo "-- \$@ 演示 ---" for i in "$@"; do echo $i done
$ chmod +x test.sh $ ./test.sh 1 2 3 -- $* 演示 --- 1 2 3 -- $@ 演示 --- 1 2 3
9.shell 基本运算符
- 原生
bash
不支持简单的数学运算,但是可以通过其他命令来实现(例:awk 和 expr
)expr
是一款表达式计算工具,使用它能完成表达式的求值操作#!/bin/bash val=`expr 2 + 2` echo "两数之和为 : $val" # 结果 两数之和为 : 4
- 注意使用的是反引号 而不是单引号
'
- 表达式和运算符之间要有空格(例:2+2 是错误的,必须写成 2 + 2)
- 完整的表达式要被
``
包含,注意这个字符不是常用的单引号,在 Esc 键下边
1.算术运算符
运算符 说明 + 加法 - 减法 * 乘法 / 除法 % 取余 = 赋值 == 相等,用于比较两个数字,相同则返回 true != 不相等,用于比较两个数字,不相同则返回 true 注意:
- 1.条件表达式要放在方括号之间,并且要有空格(例:
[$a==$b]
是错误的,必须写成[ $a == $b ]
)- 2.乘号
*
前边必须加反斜杠\
才能实现乘法运算;- 3.
MAC
中shell
的expr
语法是:$((表达式))
,此处表达式中的 乘号*
不需要转义符号\
。#!/bin/bash a=10 b=20 val=`expr $a + $b` # 等价于 val = $(($a + $b)) echo "a + b : $val" val=`expr $a - $b` echo "a - b : $val" val=`expr $a \* $b` echo "a * b : $val" val=`expr $b / $a` echo "b / a : $val" val=`expr $b % $a` echo "b % a : $val" if [ $a == $b ] then echo "a 等于 b" fi if [ $a != $b ] then echo "a 不等于 b" fi
a + b : 30 a - b : -10 a * b : 200 b / a : 2 b % a : 0 a 不等于 b
2.关系运算符
运算符 说明 -eq 检测两个数是否相等,相等返回 true -ne 检测两个数是否不相等,不相等返回 true -gt 检测左边的数是否大于右边的,如果是,则返回 true -lt 检测左边的数是否小于右边的,如果是,则返回 true -ge 检测左边的数是否大于等于右边的,如果是,则返回 true -le 检测左边的数是否小于等于右边的,如果是,则返回 true
- 关系运算符只支持数字,不支持字符串,除非字符串的值是数字
#!/bin/bash a=10 b=20 if [ $a -eq $b ] then echo "$a -eq $b : a 等于 b" else echo "$a -eq $b: a 不等于 b" fi if [ $a -ne $b ] then echo "$a -ne $b: a 不等于 b" else echo "$a -ne $b : a 等于 b" fi if [ $a -gt $b ] then echo "$a -gt $b: a 大于 b" else echo "$a -gt $b: a 不大于 b" fi if [ $a -lt $b ] then echo "$a -lt $b: a 小于 b" else echo "$a -lt $b: a 不小于 b" fi if [ $a -ge $b ] then echo "$a -ge $b: a 大于或等于 b" else echo "$a -ge $b: a 小于 b" fi if [ $a -le $b ] then echo "$a -le $b: a 小于或等于 b" else echo "$a -le $b: a 大于 b" 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.布尔运算符
运算符 说明 ! 非运算,表达式为 true 则返回 false,否则返回 true -o 或运算,有一个表达式为 true 则返回 true -a 与运算,两个表达式都为 true 才返回 true #!/bin/bash a=10 b=20 if [ $a != $b ] then echo "$a != $b : a 不等于 b" else echo "$a == $b: a 等于 b" fi if [ $a -lt 100 -a $b -gt 15 ] then echo "$a 小于 100 且 $b 大于 15 : 返回 true" else echo "$a 小于 100 且 $b 大于 15 : 返回 false" fi if [ $a -lt 100 -o $b -gt 100 ] then echo "$a 小于 100 或 $b 大于 100 : 返回 true" else echo "$a 小于 100 或 $b 大于 100 : 返回 false" fi if [ $a -lt 5 -o $b -gt 100 ] then echo "$a 小于 5 或 $b 大于 100 : 返回 true" else echo "$a 小于 5 或 $b 大于 100 : 返回 false" fi
10 != 20 : a 不等于 b 10 小于 100 且 20 大于 15 : 返回 true 10 小于 100 或 20 大于 100 : 返回 true 10 小于 5 或 20 大于 100 : 返回 false
4.逻辑运算符
运算符 说明 && 逻辑的 AND || 逻辑的 OR #!/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.字符串运算符
运算符 说明 = 检测两个字符串是否相等,相等返回 true != 检测两个字符串是否不相等,不相等返回 true -z 检测字符串长度是否为0,为0返回 true -n 检测字符串长度是否不为 0,不为 0 返回 true $ 检测字符串是否不为空,不为空返回 true #!/bin/bash a="abc" b="efg" if [ $a = $b ] then echo "$a = $b : a 等于 b" else echo "$a = $b: a 不等于 b" fi if [ $a != $b ] then echo "$a != $b : a 不等于 b" else echo "$a != $b: a 等于 b" fi if [ -z $a ] then echo "-z $a : 字符串长度为 0" else echo "-z $a : 字符串长度不为 0" fi if [ -n "$a" ] then echo "-n $a : 字符串长度不为 0" else echo "-n $a : 字符串长度为 0" fi if [ $a ] then echo "$a : 字符串不为空" else echo "$a : 字符串为空" fi
abc = efg: a 不等于 b abc != efg : a 不等于 b -z abc : 字符串长度不为 0 -n abc : 字符串长度不为 0 abc : 字符串不为空
6.文件测试运算符
操作符 说明 -b file 检测文件是否是块设备文件,如果是,则返回 true -c file 检测文件是否是字符设备文件,如果是,则返回 true -d file 检测文件是否是目录,如果是,则返回 true -f file 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true -g file 检测文件是否设置了 SGID 位,如果是,则返回 true -k file 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true -p file 检测文件是否是有名管道,如果是,则返回 true -u file 检测文件是否设置了 SUID 位,如果是,则返回 true -r file 检测文件是否可读,如果是,则返回 true -w file 检测文件是否可写,如果是,则返回 true -x file 检测文件是否可执行,如果是,则返回 true -s file 检测文件是否为空(文件大小是否大于0),不为空返回 true -e file 检测文件(包括目录)是否存在,如果是,则返回 true -S file 判断某文件是否 socket -L file 检测文件是否存在并且是一个符号链接 #!/bin/bash file="/var/www/runoob/test.sh" if [ -r $file ] then echo "文件可读" else echo "文件不可读" fi if [ -w $file ] then echo "文件可写" else echo "文件不可写" fi if [ -x $file ] then echo "文件可执行" else echo "文件不可执行" fi if [ -f $file ] then echo "文件为普通文件" else echo "文件为特殊文件" fi if [ -d $file ] then echo "文件是个目录" else echo "文件不是个目录" fi if [ -s $file ] then echo "文件不为空" else echo "文件为空" fi if [ -e $file ] then echo "文件存在" else echo "文件不存在" fi
文件可读 文件可写 文件可执行 文件为普通文件 文件不是个目录 文件不为空 文件存在
10.算术运算
- 1.$[表达式]
- 2.expr命令
- expr的内容需要用`引用,且中间内容必须空格隔开
- 3.let命令
- 变量计算中不需要加上 $ 来表示变量,需要将表达式用双引号引起来
- 4.((表达式))
11.语句结构
1.分支结构if
#结构一:不同行 if 表达式 then 命令表 [else 命令表] fi #结构二:同行(if...then...else...fi在一行需要用分号隔开) if 表达式;then 命令表;[else 命名表];fi #结构三:多层嵌套结构 if 表达式 then 命令表 [elif 表达式;then 命令表] ... [elif 表达式;then 命令表] [else 命令表] fi
- 1.
if else
的 […] 判断语句中大于使用 -gt,小于使用 -lt- 2.
if else
使用 ((…)) 作为判断语句,大于和小于可以直接使用 > 和 <- 3.
if else
也可以使用test做判断语句a=10 b=20 if [ $a == $b ] then echo "a 等于 b" elif [ $a -gt $b ] then echo "a 大于 b" elif [ $a -lt $b ] then echo "a 小于 b" else echo "没有符合的条件" fi if (( $a == $b )) then echo "a 等于 b" elif (( $a > $b )) then echo "a 大于 b" elif (( $a < $b )) then echo "a 小于 b" else echo "没有符合的条件" fi num1=$[2*3] num2=$[1+5] if test $[num1] -eq $[num2] then echo '两个数字相等!' else echo '两个数字不相等!' fi
2.分支结构case
case 表达式 in 模式1 | [模式2] |...) 命令表1;; 模式3 | [模式4] |...) 命令表2;; ... *) 命令表n;; esac
- 1.表达式:判断条件,通常是一个变量名称
- 2.命令表:可以是一个或多个命令
- 每一个模式必须以
)
结尾- 4.每一个分支以
;;
结尾- 5.
*
表示不与以上任何一个模式匹配时运行此命名表- 6.每个
case
分支用)
开始,用两个分号;;
表示break
,即执行结束- 7.检测匹配的每一个模式,一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式
- 8.如果无一匹配模式,使用星号
*
捕获该值,再执行后面的命令
3.选择结构select
select 变量 in 列表 do 命令表 done
- 1.
select
选择结构可以简便生成具有编号的菜单- 2.
select
会给列表中的内容自动生成菜单标号,下标从0开始- 3.
selsect
会根据输出的编号选择相应的内容并且赋值给相应的变量- 4.对应菜单编号可以使用
case
语言进行相应的操作
4.循环结构while
while((表达式)) do 命名表 done
- 1.通常在无法确定循环的具体次数时,使用
while
循环语句- 2.按
<Ctrl-D>
可以结束循环
5.for循环结构
for 变量 [in 列表] do 命令表 done 或 for 变量 [in 列表]; do 命令表1; 命令表2... done;
- 1.
for
循环通常用于知道具体循环次数的情况- 2.
do
和done
相当于大括号- 3.
in 列表
可以包含替换、字符串和文件名;若省略了in 列表
,则传递位置参数
6.until循环
until ((表达式)) do 命令表 done
- until 循环执行一系列命令直至条件为 true 时停止
7.break语句
- 1.使用break结束循环,跳出循环后,将转到done语句后继续执行
- 2.break 命令允许跳出所有循环(终止执行后面的所有循环)
#!/bin/bash while : do echo -n "输入 1 到 5 之间的数字:" read aNum case $aNum in 1|2|3|4|5) echo "你输入的数字为 $aNum!" ;; *) echo "你输入的数字不是 1 到 5 之间的! 游戏结束" break ;; esac done
8.continue语句
- 用来跳过本次循环,即直接跳回到循环的开始位置(条件判断处)
12.shell 函数
[function] 函数名 () { 命令表 [return] }
- 1.
shell
函数类似于shell
脚本,里面存放了一系列命令- 2.使用一个函数之前,必须创建该函数
- 3.函数返回值在调用该函数后通过
$?
来获得- 4.函数名后面的括号里面没有参数,参数是通过位置变量传递
- 4.函数中使用
exit
命令,则可以退出整个脚本- 6.如果函数退出,就返回脚本中调用该函数的地方
- 7.使用
break
语句可以中断函数的执行- 8.
[]
中的内容需要空格隔开,[]
和test
可以互换- 9.可以在脚本中运用其他文件中的函数
source 文件名
- 10.如果没有read,可以使用位置参数传递,即
函数名 位置参数1 位置参数2 。。。
- 11.注意:
$10
不能获取第十个参数,获取第十个参数需要${10}
;当n>=10时,需要使用${n}来获取参数funWithParam(){ echo "第一个参数为 $1 !" echo "第二个参数为 $2 !" echo "第十个参数为 $10 !" echo "第十个参数为 ${10} !" echo "第十一个参数为 ${11} !" echo "参数总数有 $# 个!" echo "作为一个字符串输出所有参数 $* !" } funWithParam 1 2 3 4 5 6 7 8 9 34 73
13.shell 输入/输出重定向
命令 说明 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 之间的内容作为输入
- 注意:文件描述符 0 通常是标准输入
(STDIN)
,1 是标准输出(STDOUT)
,2 是标准错误输出(STDERR)
1.输出重定向
command1 > file1
- 1.执行
command1
然后将输出的内容存入file1
- 2.注意:任何
file1
内的已经存在的内容将被新内容替代- 3.如果要将新内容添加在文件末尾,请使用
>>
操作符
2.输入重定向
command1 < file1
$ wc -l users 2 users $ wc -l < users 2 command1 < infile > outfile # 执行command1,从文件infile读取内容,然后将输出写入到outfile
3.详解重定向
一般情况下,每个
Unix/Linux
命令运行时都会打开三个文件
- 1.标准输入文件(
stdin
):stdin
的文件描述符为0
,Unix/Linux
程序默认从stdin
读取数据- 2.标准输出文件(
stdout
):stdout
的文件描述符为1
,Unix/Linux
程序默认向stdout
输出数据- 3.标准错误文件(
stderr
):stderr
的文件描述符为2
,Unix/Linux
程序会向stderr
流中写入错误信息- 4.默认情况下,
command > file
将stdout
重定向到file
,command < file
将stdin
重定向到file
# 将 stderr 重定向到 file $ command 2>file # 将 stderr 追加到 file 文件末尾 $ command 2>>file # 将 stdout 和 stderr 合并后重定向到 file $ command > file 2>&1 $ command >> file 2>&1 # 将 stdin 重定向到 file1,将 stdout 重定向到 file2 $ command < file1 >file2
4./dev/null 文件
$ command > /dev/null
- 1.执行某个命令,但又不在屏幕上显示输出结果,可以将输出重定向到
/dev/null
- 2.
/dev/null
是一个特殊的文件,写入到它的内容都会被丢弃- 3.从该文件读取内容,那么什么也读不到,但是
/dev/null
文件有用,将命令的输出重定向到它,会起到"禁止输出"的效果- 4.希望屏蔽
stdout
和stderr
,可以这样写:$ command > /dev/null 2>&1
- 5.注意:
0
是标准输入(STDIN
),1
是标准输出(STDOUT
),2
是标准错误输出(STDERR
)- 6.这里的
2
和>
之间不可以有空格,2>
是一体的时候才表示错误输出
14.shell 文件包含
. filename # 注意点号.和文件名中间有一空格 或 source filename
test1.sh 代码如下: #!/bin/bash url="http://www.baidu.com" test2.sh 代码如下: #!/bin/bash #使用 . 号来引用test1.sh 文件 . ./test1.sh # 或者使用以下包含文件代码 # source ./test1.sh echo "官网地址:$url" test2.sh 添加可执行权限并执行: 其中被包含的文件 test1.sh 不需要可执行权限 $ chmod +x test2.sh $ ./test2.sh 官网地址:http://www.baidu.com
- 1.shell 可以包含外部脚本,可以方便封装一些公用的代码作为一个独立的文件