一、基础语法
1.1 注释
1.1.1 单行注释
#! /bin/bash
# 这是临时shell脚本
echo 'hello world!'
1.1.2 多行注释
语法:
:<<字符
注释的内容
字符
#! /bin/bash
:<<! 这是临时shell脚本
这是临时shell脚本
!
echo 'hello world!'
1.2 变量
1.2.1 定义变量
- 普通变量
- 方式一:
变量名=变量值
变量值必须是一个整体,中间没有特殊字符
[root@localhost data]# number=10 [root@localhost data]# echo $number 10 [root@localhost data]# name=john [root@localhost data]# echo $name john
- 方式二:
变量名='变量值'
单引号中的内容,原样赋值
[root@localhost data]# a='$number' [root@localhost data]# echo $a $number
- 方式三:
变量名="变量值"
如果双引号里面有其他变量,会把变量的结果进行拼接,然后赋值
[root@localhost data]# b='$number' [root@localhost data]# echo $b 10
- 方式一:
- 命令变量
执行流程:先执行 ` 或者 $() 内的命令,再将执行后的结果赋值给变量。- 方式一:
变量名=`变量值`
[root@localhost data]# c=`date +%Y-%m-%d` [root@localhost data]# echo $c 2021-08-31
- 方式二:
变量名=$(命令)
[root@localhost data]# d=$(date +%Y-%m-%d) [root@localhost data]# echo $d 2021-08-31
- 方式一:
1.2.2 使用变量
- 方式一:
$变量名
- 方式二:
"$变量名"
- 方式三:
${变量名}
- 方式四:
"${变量名}"
[root@localhost data]# result="当前日期:${d}"
[root@localhost data]# echo "${result}"
当前日期:2021-08-31
1.2.3 只读变量
语法:readonly 变量名
[root@localhost data]# readonly pi=3.14
[root@localhost data]# pi=3.12
-bash: pi: readonly variable
1.2.4 删除变量
语法:unset 变量名
[root@localhost data]# name=john
[root@localhost data]# echo $name
john
[root@localhost data]# unset name
[root@localhost data]# echo $name
注意: 只读变量不能被删除
1.3 数组
1.3.1 定义数组
语法:数组名=(值1 值2 ... 值n)
[root@localhost data]# arr=(a b c d e f)
[root@localhost data]# echo ${arr[*]}
a b c d e
[root@localhost data]# echo ${arr[@]}
a b c d e
1.3.2 给数组的元素赋值
语法:数组名[索引]=值
[root@localhost data]# arr[0]=A
1.3.3 获取元素
语法:${数组名[下标]}
[root@localhost data]# echo ${arr[0]}
A
1.3.4 获取长度
语法:${#数组名[*]}
或 ${#数组名[@]}
[root@localhost data]# echo ${#arr[*]}
5
[root@localhost data]# echo ${#arr[@]}
5
1.4 运算符
1.4.1 算术运算符
运算符 | 说明 |
---|---|
+ | 加法 |
- | 减法 |
* | 乘法 |
/ | 除法 |
% | 取余 |
= | 赋值 |
++/ – | 自增,自减 |
<< / >> | 左移,右移 |
** | 求幂 |
1.4.2 算术运算
- 使用 $[] 做运算
[root@localhost data]# echo $[1+1]
2
[root@localhost data]# echo $[2*2]
4
[root@localhost data]# echo $[5/2]
2
[root@localhost data]# echo $[2<<2]
8
[root@localhost data]# echo $[5**2]
25
- 使用 expr 做运算
[root@localhost data]# expr 1 + 1
2
[root@localhost data]# echo `expr 2 \* 2`
4
[root@localhost data]# echo `expr 5 / 2`
2
- 使用内建命令 declare 做运算
[root@localhost data]# declare -i J
[root@localhost data]# J=1+1
[root@localhost data]# echo $J
2
[root@localhost data]# J=2*2
[root@localhost data]# J=5/2
[root@localhost data]# J=5**2
- 使用内建命令 let 做运算
[root@localhost data]# let "i=2+2"
[root@localhost data]# echo $i
4
[root@localhost data]# let "i=3*3"
[root@localhost data]# let "i=2<<2"
[root@localhost data]# let "i++"
[root@localhost data]# let "i=i**2"
- 使用算术扩展 $(()) 做运算
# 显示输出
[root@localhost data]# i=2
[root@localhost data]# echo $((2*(i++)))
4
[root@localhost data]# ((i++))
[root@localhost data]# echo $i
3
# 变量赋值
[root@localhost data]# var=$((i**2))
[root@localhost data]# echo $var
9
# 未定义的变量参与算术表达式求值时,会被假设为0(而不是将该变量的值赋为0)
[root@localhost data]# echo $((2*(j+1)))
2
1.5 测试
1.5.1 测试结构
test expression
[ expression ]
使用$?
来判断前一个命令的返回值,如果为 0 则判断为真,非 0 则判断为假。
1.5.2 字符串测试
字符串测试 | 说明 |
---|---|
-z “string” | 字符串 string 长度为0时返回真,否则为假 |
-n “string” | 字符串 string 长度不为 0 时返回真,否则为假 |
$“string” | 字符串 string 不为空时返回真,否则为假 |
“string1” = “string2” | 字符串 string1 和 string2 相等时返回真,否则为假 |
“string1” != “string2” | 字符串 string1 和 string2 不相等时返回真,否则为假 |
“string1” > “string2” | 按照字典排序,字符串 string1 排在 string2 之前时返回真,否则为假 |
“string1” < “string2” | 按照字典排序,字符串 string1 排在 string2 之后时返回真,否则为假 |
[root@localhost data]# a="aaa"
[root@localhost data]# b="bbb"
# 判断字符串的长度是否为0
[root@localhost data]# [ -z "$a" ]
[root@localhost data]# echo $?
1
# 判断字符串的长度是否不为0
[root@localhost data]# [ -n "$a" ]
[root@localhost data]# echo $?
0
# 判断字符串是否不为空
[root@localhost data]# [ $"$a" ]
[root@localhost data]# echo $?
0
# 判断两个字符串是否相等
[root@localhost data]# [ "$a" = "$b" ]
[root@localhost data]# echo $?
1
# 判断两个字符串是否不相等
[root@localhost data]# [ "$a" != "$b" ]
[root@localhost data]# echo $?
0
# 获取字符串的长度
[root@localhost data]# echo "${#a}"
3
1.5.3 整数比较
整数比较 | 说明 |
---|---|
num1 -eq num2 | 如果 num1 等于 num2 返回真,否则为假。eq 为 equal |
num1 -gt num2 | 如果 num1 大于 num2 返回真,否则为假。gt 为 great than |
num1 -lt num2 | 如果 num1 小于 num2 返回真,否则为假。lt 为 less than |
num1 -ge num2 | 如果 num1 大于等于 num2 返回真,否则为假。ge 为 great equal |
num1 -le num2 | 如果 num1 小于等于 num2 返回真,否则为假。le 为 less equal |
num1 -ne num2 | 如果 num1 不等于 num2 返回真,否则为假。ne 为 not equal |
[root@localhost data]# a=10
[root@localhost data]# b=20
# -eq 等于
[root@localhost data]# [ "$a" -eq "$b" ]
[root@localhost data]# echo $?
1
# -ne 不等于
[root@localhost data]# [ "$a" -ne "$b" ]
[root@localhost data]# echo $?
0
# -gt 大于
[root@localhost data]# [ "$a" -gt "$b" ]
[root@localhost data]# echo $?
1
# -lt 小于
[root@localhost data]# [ "$a" -lt "$b" ]
[root@localhost data]# echo $?
0
# -ge 大于等于
[root@localhost data]# [ "$a" -ge "$b" ]
[root@localhost data]# echo $?
1
# -le 小于等于
[root@localhost data]# [ "$a" -le "$b" ]
[root@localhost data]# echo $?
0
1.5.4 文件测试
文件测试 | 说明 |
---|---|
-e FILE | 当文件或者目录存在时返回真,否则为假 |
-f FILE | 当文件存在且为普通文件时返回真,否则为假 |
-d FILE | 当文件存在且是个目录时返回真,否则为假 |
-l FILE | 当文件存在且为链接文件时返回真,否则为假 |
-r FILE | 当文件存在且为可读文件时返回真,否则为假 |
-w FILE | 当文件存在且为可写文件时返回真,否则为假 |
-x FILE | 当文件存在且为可执行文件时返回真,否则为假 |
-s FILE | 当文件存在且大小不为0时返回真,否则为假 |
1.5.5 布尔运算符
布尔运算 | 说明 |
---|---|
! expresstion | 取反运算 |
expresstion1 -a expresstion2 | 与运算,两个表达式都为真,结果才为真 |
expresstion1 -o expresstion2 | 或运算,有一个表达式为真,则结果为真 |
[root@localhost data]# a=10
[root@localhost data]# b=20
# 取反
[root@localhost data]# [ ! "$a" -eq 10 ]
[root@localhost data]# echo $?
1
# 与运算
[root@localhost data]# [ "$a" -lt 20 -a "$b" -gt 100 ]
[root@localhost data]# echo $?
1
# 或运算
[root@localhost data]# [ "$a" -lt 20 -o "$b" -gt 100 ]
[root@localhost data]# echo $?
0
1.5.6 逻辑运算符
逻辑运算 | 说明 |
---|---|
expression1 && expression2 | 逻辑与,当两个表达式都为真时结果才为真 |
expression1 || expression2 | 逻辑或,只要有一个表达式为真结果就为真 |
[root@localhost data]# a=10
[root@localhost data]# b=20
# &&
[root@localhost data]# [[ "$a" -lt 100 && "$b" -gt 100 ]]
[root@localhost data]# echo $?
1
# ||
[root@localhost data]# [[ "$a" -lt 100 || "$b" -gt 100 ]]
[root@localhost data]# echo $?
0
# && 结合 ||,相当于 if then else
[root@localhost data]# [ "$a" -gt 100 ] && echo "成立" || echo "不 成立"
不成立
1.6 判断语句
1.6.1 if 判断语句
if 判断结构
语法:
if [ 条件 ]
then
语句体
fi
[root@localhost data]# cat if.sh
#!/bin/bash
read -p "请输入a的值:" a
read -p "请输入b的值:" b
if [ "$a" -gt "$b" ]
then
echo "a大于b"
fi
if/else 判断结构
语法:
if [ 条件 ]
then
语句体
else
语句体
fi
[root@localhost data]# cat if_else.sh
#!/bin/bash
read -p "请输入a的值:" a
read -p "请输入b的值:" b
if [ "$a" -gt "$b" ]
then
echo "a大于b"
else
echo "a小于b"
fi
if/elif/else 判断结构
语法:
if [ 条件 ]
then
语句体
elif [ 语句2 ]
语句体
else
语句体
fi
[root@localhost data]# cat if_elif_else.sh
#!/bin/bash
read -p "请输入a的值:" a
read -p "请输入b的值:" b
if [ "$a" -gt "$b" ]
then
echo "a大于b"
elif [ "$a" -lt "$b" ]
then
echo "a小于b"
else
echo "a等于b"
fi
1.6.2 case 选择语句
语法:
case 值 in
模式1)
语句体1
;;
模式2)
语句体2
;;
*)
语句体n
;;
esac
# 检测用户的输入中是否含有大写字母、小写字母或者数字
[root@localhost data]# cat case.sh
#!/bin/bash.sh
read -p "请输入一个单词:" input
echo -en "您输入的单词中包含:"
case "$input" in
*[[:lower:]]*)
echo "小写字母"
;;
*[[:upper:]]*)
echo "大写字母"
;;
*[[:digit:]]*)
echo "数字"
;;
*)
echo "无效字符"
;;
esac
1.7 循环语句
1.7.1 for 循环
语法:
for 变量 in 范围
do
循环体
done
[root@localhost data]# cat for.sh
#!/bin/bash
nums=(1 2 3 4 5)
for number in "${nums[@]}"
do
echo "$number"
done
# 类C的for循环
[root@localhost data]# cat for02.sh
#!/bin/bash
sum=0
for ((i=1; i<=100; i++))
do
let "sum+=i"
done
echo "sum=$sum"
1.7.2 while 循环
语法:
while 条件
do
循环体
done
[root@localhost data]# cat while.sh
#!/bin/bash
i=1
while [ "$i" -le 10 ]
do
echo "$i"
((i++))
done
1.7.3 until 循环
当测试结果为假时,才会继续执行语句体;当测试结果为真时停止循环。
语法:
until 条件
do
循环体
done
[root@localhost data]# cat until.sh
#!/bin/bash
i=1
sum=0
until [ "$i" -gt 100 ]
do
let "sum+=$i"
((i++))
done
echo "sum=$sum"
1.7.4 select 循环
select 是一种带有菜单选择的循环,当程序运行到 select 语句时,会自动生成可用1、2、3等数选择的列表,并等待用户输入。如果用户不输入直接按回车,select 将不会退出而是再次生成列表等待输入。
语法:
select 变量 in 范围
do
循环体
done
[root@localhost data]# cat select.sh
#!/bin/bash
months=(1 2 3 4 5 6 7 8 9 10 11 12)
select month in ${months[@]}
do
case "$month" in
3|4|5)
echo "春季"
;;
6|7|8)
echo "夏季"
;;
9|10|11)
echo "秋季"
;;
12|1|2)
echo "冬季"
;;
*)
echo "输入有误,即将退出循环" && break
;;
esac
done
1.8 函数
1.8.1 不带参数的函数
无返回值的函数
语法:
# 函数的定义 格式一
函数名(){
函数体
}
# 函数的定义 格式二
function 函数名
{
函数体
}
# 函数的调用
函数名
[root@localhost data]# cat function.sh
#!/bin/bash
method(){
echo "函数执行了!"
}
method
有返回值的函数
语法:
# 函数的定义
函数名(){
函数体
return 返回值
}
# 函数的调用
函数名
echo $?
[root@localhost data]# cat function02.sh
#!/bin/bash
file=/data/test.txt
checkFileExist(){
if [ -f "$file" ]
then
return 0
else
return 1
fi
}
checkFileExist
if [ $? -eq 0 ]
then
echo "$file 存在"
else
echo "$file 不存在"
fi
1.8.2 带参数的函数
无返回值的函数
语法:
# 函数的定义
函数名(){
函数体
}
# 函数的调用
函数名 参数1 参数2 ... 参数n
[root@localhost data]# cat function03.sh
#!/bin/bash
method(){
echo "接收到的第一个参数$1"
echo "接收到的第二个参数$2"
}
method 1 2
有返回值的函数
语法:
# 函数的定义
函数名(){
函数体
return 返回值
}
# 函数的调用
函数名 参数1 参数2 ... 参数n
echo $?
[root@localhost data]# cat function04.sh
#!/bin/bash
method(){
echo "接收到的第一个参数$1"
echo "接收到的第二个参数$2"
return $(($1+$2))
}
method 10 20
echo $?
1.8.3 递归函数
[root@localhost data]# cat factorial.sh
#!/bin/bash
method(){
local i="$1"
if [ "$i" -le 1 ]
then
result=1
else
let "m=i-1"
method "$m"
let "result=i*$?"
fi
return "$result"
}
read -p "请输入一个大于0的数字:" n
method "$n"
echo "${n}的阶乘是$?"
函数返回值
- return
- 使用 return 返回值,只能返回 1-255 的整数
- 函数使用 return 返回值,通常只是用来供其他地方调用获取状态,因此通常仅返回 0 或 1;0 表示成功,1 表示失败
- echo
- 使用 echo 可以返回任何字符串结果
- 通常用于返回数据,比如一个字符串值或者列表值
全局变量和局部变量
- 全局变量
- 不做特殊声明,Shell 中变量都是全局变量
- Tips:大型脚本程序中函数中慎用全局变量
- 局部变量
- 定义变量时,使用 local 关键字
- 函数内和外若存在同名变量,则函数内部变量覆盖外部变量