一、Shell语法(一)创建、变量、字符串
一、Shell语法(二)打印、数组、参数传递、运算符、流程控制
三、Shell语法(三)文件包含、cat、获取用户输入、printf、函数、重定向
1. echo命令
1.1 显示普通字符串
echo "hello"
1.2 显示转义字符
echo " \"这是一个带引号的字符串\" "
#打印结果:
# "这是一个带引号的字符串"
1.3 显示变量
iphone="iphone11"
echo "$iphone 5688"
#打印结果:
#iphone11 5688
1.4 显示换行
echo "iphone11 \n 5688" #错误写法,未换行
echo -e "iphone11 \n 5688" #正确写法,换行了
#打印结果:
#iphone11 \n 5688
#iphone11
#5688
-e
表示开启转义功能
1.5 不换行
echo
的打印默认会在结束时换行,加上\c
表示不换行,为了使得转义字符生效,需要在echo
后加上-e
echo -e "iphone11 5688 \c"
echo "苹果降价了"
#打印结果:
#iphone11 5688 苹果降价了
1.6 显示一个执行命令
输出当前时间,还有很多命令
echo `date`
#打印结果:
#2020年 5月22日 星期五 23时40分20秒 CST
1.7 退出命令
语法:exit 状态码
(不写状态码退出默认状态码为0)
写法一:
iphone="404报错童鞋,买了一台iPhone11,非常不好,出bug"
echo ${iphone}
exit
echo "你完蛋了,买了假货" #由于在之前已经exit,这句不执行
#打印结果:
#404报错童鞋,买了一台iPhone11,非常不好,出bug
写法二:
iphone="iphone 11"
echo ${iphone}
exit 0
echo "看看这里打印不"
#打印结果:
#iphone 11
写法三:
age=101
if [ $age -gt 100 ]
then
echo "进来了"
exit 1
fi
#打印结果
#进来了
常用命令状态如下表所示:
2. 数组
2.1 语法
数组名=(值1 值2 值3...)
2.2 初始化数组
方式一:
name=("404" "Andy" "柚芒子" "全班最菜")
echo $name
#打印结果:
#404
使用数组名打印默认输出第一个元素
方式二:
name=() #初始化一个空数组
name[0]="404"
name[1]="Andy"
name[2]="柚芒子"
name[3]="全班最菜"
echo ${name[0]} ${name[1]} #使用下标打印
#打印结果:
#404 Andy
2.3 读取数组
语法:${数组名[下标]}
name=("404" "Andy" "柚芒子" "全班最菜")
#输出一个元素
echo ${name[0]}
#输出所有->"@"和"*"表示输出所有的数据
#总结:"@"和"*"区别
#"@"->输出结果:"404" "Andy" "柚芒子" "全班最菜"
#"*"->输出结果:"404 Andy 柚芒子 全班最菜"
echo ${name[@]}
#打印结果:
#404
#404 Andy 柚芒子 全班最菜
2.4 数组长度
两种方法
一、语法:${#数组名[@]}
二、语法:${#数组名[*]}
name=("404" "Andy" "柚芒子" "全班最菜")
echo ${#name[@]}
echo ${#name[*]}
#打印结果:
4
4
获取单个数组元素字符长度
语法:${#数组名[下标]}
name=("404" "Andy" "柚芒子" "全班最菜")
echo ${#name[3]}
#打印结果:
#3
3.传递参数
3.1 语法定义
./文件名称.sh 参数1 参数2 参数3 参数4...
3.2 参数意义
${0}
表示文件名称
${1}
表示参数一
${2}
表示参数二
${3}
表示参数三
${4}
表示参数四
...
echo ${0} ${1} ${2} ${3} ${4}
#执行./hello.sh 参数1 参数2 参数3 参数4
#打印结果
#./hello.sh 参数1 参数2 参数3 参数4
3.3 特殊字符
$#
:获取脚本输入参数个数
$*
:显示整个脚本输入的参数列表
$@
:显示整个脚本输入的参数列表
echo $#
echo $*
echo $@
#执行./hello.sh 参数1 参数2 参数3 参数4
#打印结果
#4
#参数1 参数2 参数3 参数4
#参数1 参数2 参数3 参数4
4. 基本运算符
4.1 算术运算符
+
:加运算
-
:减运算
*
:乘运算
/
:除运算
%
:取余运算
=
:赋值运算
==
:判等运算符,相等返回true,不等返回false
加减乘除取余需要遵循下列语法
`expr $操作数1 $操作数2`
注意:
1.两边的引号不是单引号是键盘上1键左边的键
2.expr是shell中的规定命令,expr命令可以实现数值运算、数值或字符串比较、字符串匹配、字符串提取、字符串长度计算等功能。它还具有几个特殊功能,判断变量或参数是否为整数、是否为空、是否为0等。
案例:
a=188
b=82
echo `expr $a + $b` # 结果270
echo `expr $a - $b` # 结果106
#由于*是关键字,所以如果乘法需要在前面加上转义符号'\'
echo `expr $a \* $b` # 结果15416
echo `expr $a / $b` # 结果2
echo `expr $a % $b` # 结果24
c=$a
echo $c # 结果188
if [ $a == $b ]
then
echo "a等于b"
else
echo "a不等于b"
fi
# 输出a不等于b
4.2 关系运算符
-eq
:检测两个数是否相等,相等返回true,不相等返回false
-ne
:检测两个数是否不相等,不相等返回true,相等返回false
-gt
:检测左边数是否大于右边数,大于返回true,不是大于返回false
-lt
:检测左边数是否小于右边数,小于返回true,不是小于返回false
-ge
:检测左边数是否大于等于右边数,大于等于返回true,小于返回false
-le
:检测左边数是否小于等于右边数,小于等于返回true,大于返回false
语法:$左边操作数 关系运算符 $右边操作数
案例:
a=100
b=50
if [ $a -eq $b ]
then
echo 'a等于b'
else
echo "a不等于b"
fi
#a不等于b
if [ $a -ne $b ]
then
echo "a不等于b"
else
echo "a等于b"
fi
#a不等于b
if [ $a -gt $b ]
then
echo "a大于b"
else
echo "a小于等于b"
fi
#a大于b
if [ $a -lt $b ]
then
echo "a小于b"
else
echo "a大于等于b"
fi
#a大于等于b
if [ $a -ge $b ]
then
echo "a大于等于b"
else
echo "a小于b"
fi
#a大于等于b
if [ $a -le $b ]
then
echo "a小于等于b"
else
echo "a大于b"
fi
#a大于b
4. 基本运算符
4.1 算术运算符
+
:加运算
-
:减运算
*
:乘运算
/
:除运算
%
:取余运算
=
:赋值运算
==
:判等运算符,相等返回true,不等返回false
加减乘除取余需要遵循下列语法
`expr $操作数1 $操作数2`
注意:
1.两边的引号不是单引号是键盘上1键左边的键
2.expr是shell中的规定命令,expr命令可以实现数值运算、数值或字符串比较、字符串匹配、字符串提取、字符串长度计算等功能。它还具有几个特殊功能,判断变量或参数是否为整数、是否为空、是否为0等。
案例:
a=188
b=82
echo `expr $a + $b` # 结果270
echo `expr $a - $b` # 结果106
#由于*是关键字,所以如果乘法需要在前面加上转义符号'\'
echo `expr $a \* $b` # 结果15416
echo `expr $a / $b` # 结果2
echo `expr $a % $b` # 结果24
c=$a
echo $c # 结果188
if [ $a == $b ]
then
echo "a等于b"
else
echo "a不等于b"
fi
# 输出a不等于b
4.2 关系运算符
-eq
:检测两个数是否相等,相等返回true,不相等返回false
-ne
:检测两个数是否不相等,不相等返回true,相等返回false
-gt
:检测左边数是否大于右边数,大于返回true,不是大于返回false
-lt
:检测左边数是否小于右边数,小于返回true,不是小于返回false
-ge
:检测左边数是否大于等于右边数,大于等于返回true,小于返回false
-le
:检测左边数是否小于等于右边数,小于等于返回true,大于返回false
语法:左边操作数 关系运算符 右边操作数
案例:
a=100
b=50
if [ $a -eq $b ]
then
echo 'a等于b'
else
echo "a不等于b"
fi
#a不等于b
if [ $a -ne $b ]
then
echo "a不等于b"
else
echo "a等于b"
fi
#a不等于b
if [ $a -gt $b ]
then
echo "a大于b"
else
echo "a小于等于b"
fi
#a大于b
if [ $a -lt $b ]
then
echo "a小于b"
else
echo "a大于等于b"
fi
#a大于等于b
if [ $a -ge $b ]
then
echo "a大于等于b"
else
echo "a小于b"
fi
#a大于等于b
if [ $a -le $b ]
then
echo "a小于等于b"
else
echo "a大于b"
fi
#a大于b
4.3 布尔值运算符
!
:非运算,表达式为true则返回false,否则返回true
-o
:或运算,有一个表达式为true则返回true,都不为true则返回false
-a
:与运算,两个表达式都为true才返回true,否则返回false
案例:
a=10
b=20
if [ $a != $b ]
then
echo "不相等"
else
echo "相等"
fi
#输出:不相等
if [ $a -lt 15 -o $b -gt 15 ]
then
echo "a小于15 或者 b大于15"
else
echo "a不小于15 并且 b不大于15"
fi
#输出:a小于15 或者 b大于15
if [ $a -le 15 -a $b -ge 15 ]
then
echo "a小于15 并且 b大于15"
else
echo "a不小于15 或者 b不大于15"
fi
#输出:a小于15 并且 b大于15
4.4 逻辑运算符
&&
:逻辑且 (AND)
||
:逻辑或 (OR)
案例:
a=10
b=20
if [ $a -lt 15 ] && [ $b -gt 15 ]
then
echo "a小于15 且 b大于15"
else
echo "a不小于15 或 b不大于15"
fi
#输出 a小于15 且 b大于15
if [ $a -gt 15 ] || [ $b -gt 15 ]
then
echo "a大于15 或 b大于15"
else
echo "a不大于15 且 b不大于15"
fi
#输出 a大于15 或 b大于15
4.5 字符串运算符
=
,==
:判断两个字符串是否相等,如果相等返回true
!=
:判断两个字符串是否不相等,如果不相等返回true
-z
:检测字符串长度是否为0,为0返回true
-n
:检测字符串长度是否不为0,不为0返回true
str
:检测字符串是否为空,不为空返回true
a="abc"
b="abc"
#注意:这里用=或者==都可以
if [ $a = $b ]
then
echo "a和b相等"
else
echo "a和b不相等"
fi
#输出 a和b相等
b="123"
if [ $a != $b ]
then
echo "a和b不相等"
else
echo "a和b相等"
fi
#输出 a和b不相等
a=''
if [ -z "$a" ]
then
echo "字符串a的长度为0"
else
echo "字符串a的长度不为0"
fi
#输出 字符串a的长度为0
if [ -n "$a" ]
then
echo "字符串a的长度不为0"
else
echo "字符串a的长度为0"
fi
#输出 字符串a的长度为0
if [ str $a ]
then
echo "字符串a为空"
else
echo "字符串a不为空"
fi
#输出 字符串a为空
注意
-
在中括号中,使用
-z
,-n
判断变量的值,加不加双引号的问题?a="123" [ -z "$p" ] #单对中括号变量必须加双引号 [[ -n $a ]] #双对中括号,变量不用加双引号
多个条件判断,[]和[[]]的区别?
- [[]]双对中括号,是不能使用
-a
、-o
参数进行比较的,只能用&&
、||
- []可以使用
-a
、-o
,但是-a
、-o
必须写在中括号内部,如果想在中括号外面判断两个条件,必须使用&&
、||
- 当判断某个变量的值是否满足正则表达式的时候,必须使用[[]]双对中括号
更多关于括号的详细介绍请参照:shell中各种括号的作用()、(())、[]、[[]]、{}
4.6 文件测试运算符
-d file
:检测文件是否是目录,是目录返回true
-r file
:检测文件是否可读,可读则返回true
-w file
:检测文件是否可写,可写则返回true
-x file
:检测文件是否可执行,可执行返回true
-f file
:检测文件是否是普通文件(既不是目录,也不是设备文件),如果是普通文件则返回true
-s file
:检测文件是否为空(文件大小是否大于0),不为空返回true
-e file
:检测文件(包括目录)是否存在,如果是,则返回true
-c file
:检测文件是否存在且为字符型特殊文件,如果是,则返回true
-b file
:检测文件是否存在且为块特殊文件,如果是,则返回true
file="hello.sh"
if [ -d $file ]
then
echo "是目录"
else
echo "不是目录"
fi
#输出 不是目录
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 [ -s $file ]
then
echo "文件不为空"
else
echo "文件为空"
fi
#输出 文件不为空
if [ -e $file ]
then
echo "文件存在"
else
echo "文件不存在"
fi
#输出 文件存在
5.流程控制
5.1 if语句
语法结构:
if [ 条件 ]
then
代码
elif [ 条件 ]
代码
else
代码
fi
结构中的elif分支和else分支可以没有
5.2 for循环语句
- for-in语法结构:
for 变量名 in item1 item2 item3 ...
do
代码
done
案例:
#一、读取简单的列表
for name in "张三" "李四" "王五" "赵六"
do
echo -e "$name \c"
done
#打印结果
#张三 李四 王五 赵六
#二、读取列表复杂的值
for name in I don\'t know
do
echo $name
done
#打印结果
#I
#don't
#know
list="I don't know"
for name in $list
do
echo $name
done
#打印结果
#I
#don't
#know
#*为通配符
file="/Users/liu_david/Desktop/学习/*"
for item in $file
do
echo $item
done
#打印结果
#/Users/liu_david/Desktop/学习/Flutter学习
#/Users/liu_david/Desktop/学习/iOS学习
#/Users/liu_david/Desktop/学习/面试相关
#/Users/liu_david/Desktop/学习/学习的项目
#/Users/liu_david/Desktop/学习/数据结构学习
#/Users/liu_david/Desktop/学习/优秀第三方库.rtf
- 类似c中的for循环
for ((a=1;a<5;a++))
do
echo $a
done
#打印结果
#1
#2
#3
#4
#嵌套循环
for ((a=1;a<5;a++))
do
echo "a=$a"
for ((b=1;b<5;b++))
do
echo "b=$b"
done
done
#打印结果
#a=1
#b=1
#b=2
#b=3
#b=4
#a=2
#b=1
#b=2
#b=3
#b=4
#a=3
#b=1
#b=2
#b=3
#b=4
#a=4
#b=1
#b=2
#b=3
#b=4
5.3 while循环语句
语法结构:
while(条件)
do
代码
done
案例
a=1
while(($a<5))
do
echo ${a}
a=`expr $a + 1`
done
#打印结果
#1
#2
#3
#4
a=1
while [ $a -lt 10 ]
do
echo $a
a=`expr $a + 1`
done
#打印结果
#1
#2
#3
#4
#5
#6
#7
#8
#9
无限循环:
while :
do
echo "Hello"
done
while true
do
echo "Hello"
done
for((;;))
do
echo "Hello"
done
5.4 case语句(类似于C语音中的Switch-case语句)
语法结构
case 值 in
模式1)
代码
;;
模式2)
代码
;;
模式3)
代码
;;
esac
案例
number=2
case $number in
1)
echo "等于1"
;;
2)
echo "等于2"
;;
3)
echo "等于3"
;;
esac
#打印结果
#等于2
5.5 until循环
语法结构
until 条件
do
代码
done
不满足条件,则进入do后面的代码段
案例
number=1
until [ $number -ge 5 ]
do
echo "number为$number,小于5"
number=`expr $number + 1`
done
#打印结果
#number为1,小于5
#number为2,小于5
#number为3,小于5
#number为4,小于5
5.6 跳出循环break、continue
break
- 跳出单个循环
for ((i = 0;i < 10;i++))
do
echo "当前i的值:$i"
if [ $i -eq 5 ]
then
echo "跳出循环"
break
fi
done
#打印结果
#当前i的值:0
#当前i的值:1
#当前i的值:2
#当前i的值:3
#当前i的值:4
#当前i的值:5
#跳出循环
- 跳出内部循环
for ((i = 0;i < 3;i++))
do
echo "外层循环i的值:$i"
for ((j = 0;j < 5;j++))
do
echo "内层循环j的值:$j"
if [ $j -eq 2 ]
then
echo "退出内层循环,执行下一个操作"
break
fi
done
done
#打印结果
#外层循环i的值:0
#内层循环j的值:0
#内层循环j的值:1
#内层循环j的值:2
#退出内层循环,执行下一个操作
#外层循环i的值:1
#内层循环j的值:0
#内层循环j的值:1
#内层循环j的值:2
#退出内层循环,执行下一个操作
#外层循环i的值:2
#内层循环j的值:0
#内层循环j的值:1
#内层循环j的值:2
#退出内层循环,执行下一个操作
- 跳出外部循环
for ((i = 0;i < 3;i++))
do
echo "外层循环i的值:$i"
for ((j = 0;j < 5;j++))
do
echo "内层循环j的值:$j"
if [ $j -eq 2 ]
then
echo "退出循环"
break 2
fi
done
done
#打印结果
#外层循环i的值:0
#内层循环j的值:0
#内层循环j的值:1
#内层循环j的值:2
#退出循环
break 数字
默认只写break和break 1的结果相同,表示退出一层循环
break 数字 后面的数字是几,就表示退出几层循环(从break所在位置往外数的几层),如果后面的数字大于实际有的层级,那么和退出全部循环的意义相同,比如上方示例为break 3,也和break 2退出两层循环意义相同。
注意:数字不能为0,最小为1的整数,表示退出一层循环
continue
- 执行下一次循环
for ((i = 0; i < 5; i++))
do
echo "循环i值:${i}"
if [ ${i} -ge 2 ]
then
echo "执行下一次循环"
continue
fi
echo "如果前面continue了这里就不会执行了"
done
#打印结果
#循环i值:0
#如果前面continue了这里就不会执行了
#循环i值:1
#如果前面continue了这里就不会执行了
#循环i值:2
#执行下一次循环
#循环i值:3
#执行下一次循环
#循环i值:4
#执行下一次循环
- 继续执行外层循环的下一步
for ((i = 0;i < 2;i++))
do
echo "外层循环i的值:$i"
for ((j = 0;j < 5;j++))
do
echo "内层循环j的值:$j"
if [ $j -eq 2 ]
then
echo "继续执行外部循环的下一步"
continue 2
fi
done
echo "这里是测试"
done
#打印结果
#外层循环i的值:0
#内层循环j的值:0
#内层循环j的值:1
#内层循环j的值:2
#继续执行外部循环的下一步
#外层循环i的值:1
#内层循环j的值:0
#内层循环j的值:1
#内层循环j的值:2
#继续执行外部循环的下一步
这里的continue 数字,数字的含义和break 数字的含义一样,如果数字大于循环的层次,则是继续执行最外部循环的下一步