由于工作中会用到shell,所以通过看视频学习了shell的语法,本篇文章简单记录一下学习成果,这样可以让我在使用时能快速找到样例,进行模仿编写,也是对初学shell的一种总结。
如果想要全面了解shell,那么可以在GNU官网了解:https://www.gnu.org/software/bash/
变量
命名规则
变量由字母、数字、下划线组成
区分大小写
数字不能开头
不能使用关键字
变量赋值
变量通过等于号来赋值。等号左侧为变量名,右侧为变量的值,将右侧的值赋值给左侧的变量,等号两边不要有空格。
变量的值为整数:
a=1
b=10+5
变量的值为字符串:
c=hello
c1=hello world # 错误写法
c2="hello world"
c3='hello world'
c4='hello, I'm Bob' # 错误写法,单引号会出现匹配问题
c5="hello, I'm Bob" # 双引号包裹单引号
引用变量
方式1:$变量名
方式2:${变量名},建议使用该方式引用变量
echo 变量
可以打印变量的值
举例如下,(为方便举例,下文使用了前文已定义好的变量):
echo $c # 打印变量c,终端将显示:hello
echo ${c} # 打印变量c,终端将显示:hello
echo $cworld # 不显示(终端只能看到一个空白行),因为没有定义变量cworld
echo ${c}world # 显示:helloworld
echo "${c}world" # 显示:helloworld
echo "{$c}world" # 显示:{hello}world
echo $d
使用变量时,时常会将变量用双引号包裹起来,这样能尽量保证不出错。例如:
a="hello world" # 注意hello和world之间有空格
test $a = "hello world" # test命令1,会报错:-bash: test: too many arguments
test "$a" = "hello world" # test命令2,不会报错
test命令1会报错,因为test命令1等价于:test hello world = "hello world"
, 等于号左侧的hello world并没有加双引号,那么bash在解析时就会出问题,因为等于号左侧只能有1个值,而空格会让bash认为有2个值。
test命令2不会报错,它等价于:test "hello world" = "hello world"
,由于双引号包裹了hello world,所以bash任务等于号左侧是1个字符串,是1个值。
数组
定义数组如下:
d=( 1 2 3 )
d1=( 1 2 "3" 4 )
d2=( "This" "is" "my" "home." ) # 等价于 d1=( This is my home.)
bash shell只支持一维数组。
数组要用一对()括起来
数组中的每个元素使用空格隔开。
获取数组元素。${d[*]}
或${d[@]}
: 获取数组d的全部元素${#d[*]}
: 获取数组d的元素个数${d[index]}
: 获取数组d中索引为index的元素,数组元素的索引按照从左往右、计数从0开始的顺序递增。索引也可以使用负数表达倒数第几个元素。
示例如下:
# 变量$d
echo ${d[*]} # 打印:1 2 3
echo ${d[@]} # 打印:1 2 3
echo ${#d[*]} # 打印:3,变量d共有4个元素,等价于:${#d[@]}
echo ${d[2]} # 打印:3,变量d中元素1、2、3的索引分别为0、1、2
echo ${d[-2]} # 打印:2,变量d中倒数第2个元素是2
# 变量$d2
echo ${d2[*]} # 打印:This is my home.
echo ${d2[@]} # 打印:This is my home.
echo ${#d2[*]} # 打印:4,变量d2共有4个元素, 等价于:${#d2[@]}
echo ${d2[1]} # 打印:is,变量d2中元素This、is、my、home.的索引分别为0、1、2、3
echo ${d2[-2]} # 打印:my,变量d2中倒数第2个元素是my
test命令
test命令可以用来检测文件是否存在、判断表达式是否正确等等。完整的test命令可以在linux终端上使用man test命令查看。下面介绍一下test命令的常用用法。
test命令检测文件:
test -e /var/log/nginx.log # -e参数表示文件是否存在
test -f /var/log/nginx.log # -f参数表示文件是否存在,且文件是个普通文件
test -d /var/log # -d参数表示文件是否存在,且文件是一个目录
test -x /tmp/1.sh # -x参数表示文件是否有x权限
test命令检测表达式是否正确,格式test <expression>
;在表达式中,运算符与两侧数字要有空格才行。
test 1=2 # 错误的用法,比较运算符“=”两边必须有空格,其它比较运算符类似
test 1 = 2 # 判断1是否等于2
test 1 -eq 2 # 判断1是否等于2,=和-eq等价
test 1 > 0 # 判断1是否大于0
test 1 -gt 0 # 判断1是否大于0,>和-gt等价
还可以使用中括号来省略test命令前缀:
# 正确用法
[ 1 = 2 ] # 判断1是否等于2, 等价于:test 1 = 2
[ 1 -eq 2 ] # 判断1是否等于2, 等价于:test 1 -eq 2
# 错误的用法
[1 = 2] # 错误的用法1,中括号与表达式之间要有空格
[ 1 = 2] # 错误的用法2,中括号与表达式之间要有空格
运算符
shell脚本中的运算符大致分为以下几类:用于计算的算数运算符、用于比较的关系运算符(比较运算符)等等。
算数运算符
中文含义 | 运算符 |
---|---|
相加 | + |
相减 | - |
相乘 | * |
相除 | / |
取余 | % |
赋值 | = |
比较运算符
中文含义 | 比较运算符1 | 比较运算符2 |
---|---|---|
是否相等 | = | -eq |
不相等 | != | -ne |
大于 | > | -gt |
大于等于 | 无 | -ge |
小于 | < | -lt |
小于等于 | 无 | -le |
逻辑运算符
中文含义 | 逻辑运算符 |
---|---|
与 | && |
或 | || |
非 | ! |
其它运算符
中文含义 | 运算符 |
---|---|
检测字符串长度是否为0 | -z |
检测字符串长度是否不为0 | -n |
举例:
[ -z "hello" ] # 表达式返回假
[ -n "hello" ] # 表达式返回真
[ -z "" ] # 表达式返回真
[ -n "" ] # 表达式返回假
if分支
if分支结构有常用的三种:if,if-else,if-elif-else,它们之间可以互相嵌套。
格式
if格式:
if <条件> then
<执行语句>
fi
if-else格式:
if <条件> then
<执行语句1>
else
<执行语句2>
fi
if-elif-else格式:
if <条件1> then
<执行语句1>
elif <条件2> then
<执行语句2>
else
<执行语句3>
fi
示例
如果年龄大于18岁则为成年人
if [ $age -ge 18 ] then
echo "成年人"
# 等价于
if test $age -ge 18 then
echo "成年人"
如果年龄大于等于18岁为成年人,否则为未成年人
if [ $age -ge 18 ] then
echo "成年人"
else
echo "未成年人"
fi
如果年龄大于等于60则为老年人,年龄在[40, 60)的为中年人,年龄在[18, 40)的为青年人,年龄在[0, 18)的为未成年人
if [ $age -ge 60 ] then
echo "老年人"
elif [ $age -ge 40 ] then
echo "中年人"
elif [ $age -ge 18 ] then
echo "青年人"
else
echo "未成年人"
fi
while循环
满足条件时,执行循环体
格式
while <条件>
do
<代码块>
done
示例
打印1到5,每次打印后变量+1
age=1
while [ $age -le 5 ]
do
echo $age
age=$(( age + 1 ))
done
# 输出示例
1
2
3
4
5
until循环
执行循环,直到满足条件时停止
格式
until <条件>
do
<代码块>
done
示例
打印age并自减去1,直到age小于等于0停止
age=5
until [ $age -le 0 ]
do
echo $age
age=$(( age - 1 ))
done
# 输出示例
5
4
3
2
1
for循环
for循环有两种格式:for-in和c风格的for
格式
for-in格式如下:
for <变量> in <值1> <值2> <值3> <值4> ...
do
<代码块>
done
c风格的for如下:
for (( <初始变量>; <循环条件>; <变量变化> ))
do
<代码块>
done
示例
for-in形式
for world in This is my home.
do
echo $world
done
# 输出结果
This
is
my
home.
c风格的for
for (( a=1; a<5; a++ ))
do
echo $a
done
# 输出结果
1
2
3
4
结束循环
分为break和continue
break 结束整个循环
题目:打印1到5,如果遇到偶数,则不打印并且结束整个循环。
# while写法
a=1
while [ $a -le 5 ]
do
if [ $(( a % 2 )) = 0 ]; then
break
fi
echo $a
a=$(( a + 1))
done
# for写法1
for a in 1 2 3 4 5
do
if [ $(( a % 2 )) = 0 ]; then
break
fi
echo $a
done
# for写法2
for (( a = 1; a <= 5; a++ ))
do
if [ $(( a % 2 )) = 0 ]; then
break
fi
echo $a
done
continue 结束本次循环,继续下一个循环
题目:打印1到5,如果遇到偶数,则不打印并且跳过本次循环。
# while写法
a=1
while a -le 5
do
if [ $a % 2 = 0 ] then
continue
fi
echo $a
a=$(( a + 1))
done
shell中各种括号:()、(())、[]、[[]]、{}
参考:https://www.runoob.com/w3cnote/linux-shell-brackets-features.html