备课😳,复习(预习)一下shell
脚本的基本语法。
shell基本语法
shell
脚本可以将完成一个任务的所有命令按照执行的先后顺序,自上而下地写入到一个文件,并给予执行权限。
脚本运行方法
- 赋予运行权限
- 使用
bash
执行
chmod +x demo.sh
./demo.sh
# 或者
bash demo1.sh
shell常用符号
~: # home 目录
!: # 执行历史命令,!! 执行上一条命令
$: # 变量取内容符,$USER
+ - * / % # 加减乘除
&: # 后台运行
*: # 通配符,匹配所有
?: # 通配符,匹配除回车外的一个字符
;: # 一行执行多个指令的时候用作分割
|: # 管道符,将上一个命令的输出作为下一个命令的输入
\: # 转义字符
``: # 反引号,在命令中执行命令,可类比于python中的exec()函数
': # 单引号,shell中的字符串需要使用 单引号括起来,与双引号不同的是单引号不解释变量 '$USER'
": # 双引号,脚本中出现的字符可以使用双引号括起来 "$USER" 会解释变量
>: # 输出重定向符 只用一个 > 会覆盖文件 ,用两个 >> 会追加文件
<: # 输出重定向符,只用一个 就是只输入一次,两个 << 就是追加输入(可以用于交互式的命令输入例如fdosk),使用 <<EOF表示结束书输入
$?: # 通过上一个命令的 exit code判断上一条命令是否执行成功,为0则代表执行成功,否则为执行失败。expr 1 + 1 &>/dev/null; echo $?可以用分号分隔上一个命令,从而达到判断执行是否成功的作用
shell 数学运算
shell
中完成数学运算的方式有很多种
expr
表达式let
表达式。(())
表达式
注意1:expr 表达式中运算符的前后必须要有空格
注意2:expr 表达式中使用乘运算符 * 时需要使用转义符
注意3:let 表达式中=前后不能有空格
# expr 表达式
expr 1 + 1
expr 1 - 1
expr 3 \* 4
expr 9 / 3
expr 10 % 3
# `let`可以完成同样的功能,但必须要一个变量缓存计算结果
let sum=1+2
# (()) 中对表达式没有要求,使用乘法时也不需要转义
echo $((1+1))
echo $((100 * 3))
当运算中需要使用小数时,可以使用管道运算符|
配合bc
命令完成 (bc可能需要单独安装 )
bc
中使用scale=n
制定保留小数的位数
echo "scale=2;100/3"|bc
# 上面的输出为 33.33
echo "当前内存占用为: `echo "scale=2;100/3"|bc`%"
# 当前内存占用为 33.33%
shell退出
exit code 的范围为8位,即0-255
exit 0 # 表示正常退出
echo $? # 查看上一条指令是否正常执行并退出
shell 输入输出
read
命令可以从终端读入内容
read acc # 将输出内容保存到 变量acc中
read -s passwd # 输出内容保存到 passwd中,且输入的时候输入内容不回显,一般用于密码输入
read -p "这里是提示:" abc #-p 指定输入时的提示
read -n6 abc # 输入的长度只能为6
read -t5 abc # 只能在 5s 内输入,超过时间后执行下一行
echo
命令的作用是在显示器中输出一段提示文字。常用用法和参数如下
echo "hello world!" # 普通输出,输出后换行
echo -n "hello world!" # 输出后不换行
echo -e "\t abc" # 输出字符串中包含有特殊的转义字符时使用
shell的变量
变量的分类与定义语法
shell
中变量类型分为三种,其中本地和全局变量都属于环境变量。
- 本地变量:用户私有变量,只有本用户读取或修改,保存在
.bash_profile
和.bashrc
文件中 - 全局变量:所有用户都可以使用,保存在
/etc/profile
和/etc/.bashrc
中 - 用户自定义变量:用户自定变量,例如在脚本中定义的变量
变量名在定义时不需要加$
,但是在使用的时候需要加$
符号。
定义变量的格式为:变量名=值。将变量设置成全局变量的时候需要加上前缀 export
注意:变量名和等号之间不能有空格
# 定义一个临时变量,在终端关闭或者重启之后该变量会被清除
VAR1=1
AGE=18
# 手动清除一个变量
unset VAR1
# 定义一个全局变量
export GENDER='MALE'
变量名最好全部写成大写以示区分
数组变量
数组可以将一系列的内容保存到同一个变量中,在访问时通过下标进行访问。
定义数组:数组名称=(元素1 元素2 元素3 ....)
各个元素之间通过空格隔开。
数组的访问 : ${数组[下标]}, 下标从0开始
注意: bash 默认下标从0开始,但是zsh的下标默认从1开始
# 单个赋值
arr0[0]='abc'
arr0[1]='def'
arr1=('tom' 'jack' 'rose') # 连续赋值
arr1=(`cat /etc/passwd`) # 将文件的行读入作为一个数组
echo ${arr1[@]} # @ 符号代表数组所有的成员
echo ${#arr1[@]} # 获取数组的长度
echo ${!arr1[@]} # 打印数组的索引,备注:zsh不支持
echo ${arr1[@]:1} # 切片,从1开始的元素
echo ${arr1[@]:1:2} # 切片,从1开始访问两个元素
shell
中的关联数组可以类比字典类型,可以自定义索引访问
declare -A r_arr
# 连续赋值
r_arr=([name]='tom' [age]='18')
# 或者单独赋值
r_arr=([gender]='male')
# 访问关联数组
echo "${r_arr[name]}"
流程控制
常见的运算符号
shell
中没有 >=,<=
之类的判断符号,整数数学的比较运算运算符有下面这些
-eq 等于
-gt 大于
-lt 小于
-ge 大于或等于
-le 小于或等于
-ne 不等于
# 用法
test 1 -q 1;echo $?
常见的文件的判断运算符
-d 检查文件是否存在且为目录
-e 检查文件是否存在
-f 检查文件是否存在且为文件
-r 检查文件是否存在且可读
-w 检查文件是否存在且可写
-x 检查文件是否存在且可执行
常见的字符串比较运算
== 等于
!= 不等于
-n 检查字符串长度是否大于0
-z 检查字符串长度是否为0
# 用法
test -z ""; echo $?
test 'abc'=='bcd';echo $?
逻辑运算
! 取反
&& 逻辑与
|| 逻辑或
if 语句
if
语句的格式如下,condition中可以使用前面所提到的逻辑运算符将条件连接起来
if [ condition ]
then
commands
fi
if [ condition ]
then
commands
else
commands
fi
if [ condition ]
then
commands
elif [ ]
commands
else
commands
fi
用法举例
# 可以使用 $1 ,$2 等变量获取传入的命令行参数
if [ $1 -eq $2 ]
then
echo "等于"
else
echo "不等于"
fi
for 循环语句
第一种for
语句的语法
for var in value1 value2
do
commands
done
#例子,seq 是一个shell 命令,可以生成指定范围内的数字序列
# 1 直接赋值
for x in 1 2 3 4 5 6 7 8 9
do
echo ${x}
done
# 2 使用 shell 命令赋值
for var in `seq 1 9`
do
echo ${var}
done
# seq 的用法
# seq [start] [step] [end]
# seq [start] [end]
# 3 可以直接用字符串赋值,使用 空格分隔
for var in hello peter, i\'m Doctor Octopus
do
echo $var
done
第二种for
语句的语法, 类似于 C语言的写法
for ((i=1;i<10;i++))
do
echo ${i}
done
# 可以由多个条件,condition 两边记得加空格
for (( a=1,b=1;a<100;a++,b++ ))
do
echo "${a},${b}"
done
while 和 until 循环
while
语句
while condition
do
command
done
# 例子
int=1
while(( $int<=5 ))
do
echo $int
let "int++"
done
until
语句
until condition
do
command
done
# 用法
a=0
until [ ! $a -lt 10 ]
do
echo $a
a=`expr $a + 1`
done
case 语句
当有多个分支时除了可以使用if elif ...
这种结构还可以使用 case
语句进行分支选择
case value in
pattern1)
commands
;;
pattern2)
commands
;;
...
*)
commands
;;
esac
# 例子
echo '输入 1 到 4 之间的数字:'
echo '你输入的数字为:'
read aNum
case $aNum in
1) echo '你选择了 1'
;;
2) echo '你选择了 2'
;;
3) echo '你选择了 3'
;;
4) echo '你选择了 4'
;;
*) echo '你没有输入 1 到 4 之间的数字'
;;
esac
循环控制
流程控制一般包含有 continue
和break
语句用于控制循环的执行
while # 不加任何条件语句则表示死循环
do
read a
if [ a -eq 0]
then
break
elif [ a -eq 1 ]
continue
else
echo "your number is ${a}"
fi
done
shell函数
定义函数的语法有两种,分别为
# 语法一
func_name ()
{
commands
return N
}
# 语法二
function func_name ()
{
commands
return N
}
# 函数参数例子
function hell0_func ()
{
echo "hello $1" # $1 代表第一个函数参数,$0是当前的脚本文件名
}
$# # 函数的参数个数
$? # 最后一个命令的退出状态,为 0 表示没有错误
调用函数的方法比较奇怪,不需要加()
,需要传参的话直接写在后面就可以了
# 函数传参的例子
hello_func alex
# 带返回值函数调用的例子
funWithReturn(){
echo "这个函数会对输入的两个数字进行相加运算..."
echo "输入第一个数字: "
read aNum
echo "输入第二个数字: "
read anotherNum
echo "两个数字分别为 $aNum 和 $anotherNum !"
return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? !"