Shell变量操作
1 数值变量运算
shell 变量的数值运算多用于脚本程序的过程控制。
1.1 expr命令
整数值的运算主要通过内部命令 expr 进行
- 语法:expr 变量1 运算符 变量2 运算符 变量3…
变量 1、变量 2……对应为需要计算的数值变量(需要以“$”符号调用)
运算符与变量之间必须有至少一个空格
- 常见运算符
+:加法运算
-:减法运算
\*
:乘法运算,不能直接使用*,会被当成通配符/:除法运算,整除
%:取余运算
x=7
y=3
expr $x + $y
expr $x - $y
expr $x \* $y
expr $x / $y
expr $x % $y
若要将运算结果赋值给其他变量,可以结合命令替换操作
# 使用反撇号``
y3=`expr $y \* $y \* $y`
echo $y3
# 使用$()
y3=$(expr $y \* $y \* $y)
echo $y3
1.2 let命令
let 命令允许在Shell中进行算术运算,可以用来增加、减少或对变量进行其他数学操作。
语法:let 算数表达式
# 赋值
let a=10
echo $a
# 自增
let a++
echo $a
let a+=1
echo $a
# 自减
let a--
echo $a
let a-=1
echo $a
- i++与++i
a=i++:先将i的当前值赋值给a,然后i再加1
a=++i:先将i的当前值+1,然后再赋值给a
let i=10
echo $i
let a=i++
echo $a $i
let a=++i
echo $a $i
1.3 非正数运算
bash 不支持浮点运算,如果需要进行浮点运算,需要借助bc,awk等程序处理。
1.3.1 bc
bc是一个简单易用的计算器程序,可以用于执行基本的数学运算,包括加、减、乘、除和取余等操作。
在Shell编程中,可以使用bc命令将数学表达式计算结果输出到标准输出或保存到文件中,以满足不同的需求。
浮点数运算中:使用scale=n,确定保留几位小数,要使用双引号
- vim bc.sh
#!/bin/bash
# 加法
f=$(echo "3.9+1.9"|bc)
echo "3.9+1.9=$f"
# 减法
f=$(echo "3.9-1.9"|bc)
echo "3.9-1.9=$f"
# 乘法
f=$(echo "3.9*1.9"|bc)
echo "3.9*1.9=$f"
# 除法,保留三位小数
f=$(echo "scale=3;3.9/1.9"|bc)
echo "3.9/1.9=$f"
# 混合运算
f=$(echo "(3.9+1.9)*2-3.1"|bc)
echo "(3.9+1.9)*2-3.1=$f"
- source bc.sh
1.3.2 awk
- vim awk.sh
#!/bin/bash
# 加法
f=$(awk 'BEGIN{print 3.6+1.2}')
echo "3.6+1.2=$f"
# 减法
f=$(awk 'BEGIN{print 3.6-1.2}')
echo "3.6-1.2=$f"
# 乘法
f=$(awk 'BEGIN{print 3.6*1.2}')
echo "3.6*1.2=$f"
# 除法
f=$(awk 'BEGIN{print 3.6/1.2}')
echo "3.6/1.2=$f"
# 混合运算
f=$(awk 'BEGIN{print (3.6-1.2)/2+2.4}')
echo "(3.6-1.2)/2+2.4=$f"
- source awk.sh
2 数值布尔运算
2.1 条件测试操作
Shell 环境根据命令执行后的返回状态值($?)来判断是否执行成功,当返回值为 0 时表示成功,否则(非 0值)表示失败或异常。
使用专门的测试工具:test 命令,可以对特定条件进行测试,并根据返回值来判断条件是否成立(返回值为 0 表示条件成立)。
语法:test 条件表达式 或 [ 条件表达式 ]
两种方式的作用完全相同,但通常后一种形式更为常用,也更贴近编程习惯。
需要注意,方括号与条件表达式之间需要至少一个空格进行分隔。
2.2 关系运算符:整数值比较
只能用来进行整数值的比较,根据给定的两个整数值,判断第一个数与第二个数的关系,如是否大于、等于、小于第二个数。
常用选项:
选项 | 说明 |
---|---|
-eq | 第一个数等于(Equal)第二个数 |
-ne | 第一个数不等于(Not Equal)第二个数 |
-gt | 第一个数大于(Greater Than)第二个数 |
-lt | 第一个数小于(Lesser Than)第二个数 |
-ge | 第一个数大于或等于(Greater or Equal)第二个数 |
-le | 第一个数小于或等于(Lesser or Equal)第二个数 |
关系运算符只支持数字,不支持字符串,除非字符串的值是数字。
- vim test.sh
#!/bin/bash
a=10
b=20
# 等于
test $a -eq $b
echo $?
# 不等于
[ $a -ne $b ]
echo $?
# 判断a、b是否相等
if [ $a -eq $b ]
then echo "a 等于 b"
else echo "a 不等于 b"
fi
- source test.sh
2.3 逻辑运算
逻辑测试指的是判断两个或多个条件之间的依赖关系。
当系统任务取决于多个不同的条件时,根据这些条件是否同时成立或者只要有其中一个成立等情况,需要有一个测试的过程。
常用的逻辑测试操作如下,使用时放在不同的测试语句或命令之间。
&&:逻辑与,表示“而且”,只有当前后两个条件都成立时,整个测试命令的返回值才为 0(结果成立)。使用 test 命令测试时,“&&”可改为“-a”。
||:逻辑或,表示“或者”,只要前后两个条件中有一个成立,整个测试命令的返回值即为 0(结果成立)。使用 test 命令测试时,“||”可改为“-o”。
!:逻辑否,表示“不”,只有当指定的条件不成立时,整个测试命令的返回值才为 0(结果成立)。
- vim test2.sh
#!/bin/bash
a=10
b=20
# 逻辑否
[ ! $a -eq $b ]
echo $?
# 逻辑与
[ $a -ne 5 ] && [ $b -eq 20 ]
echo $?
# 逻辑或
[ $a -lt 5 ] || [ $b -gt 5 ]
echo $?
- source test2.sh
3 字符串比较
符串比较通常用来检查用户输入、系统环境等是否满足条件,在提供交互式操作的Shell 脚本中,也可用来判断用户输入的位置参数是否符合。
常见操作:
操作符 | 说明 |
---|---|
= | 判断字符串是否相等,相等返回true |
!= | 判断字符串是否不相等,不相等返回true |
-z | 判断字符串长度是否为0,为0返回true |
-n | 判断字符串长度是否不为0,不为0返回true |
$ | 判断字符串是否为空,不为空返回true |
- vim str.sh
#!/bin/bash
a="aaa"
b="bbb"
c=""
# 判断字符串是否相等
if [ $a = $b ]
thenecho "$a 等于 $b"
elseecho "$a 不等于 $b"
fi
# 判断字符串是否不相等
if [ $a != $b ]
thenecho "$a 不等于 $b"
elseecho "$a 等于 $b"
fi
# 判断字符长度是否为0
if [ -z $c ]
thenecho "c 字符长度为0"
elseecho "c 字符长度不为0"
fi
# 判断字符长度是否不为0,变量加上双引号
if [ -n "$c" ]
thenecho "c 字符长度不为0"
elseecho "c 字符长度为0"
fi
# 判断字符串是否为空
if [ $c ]
thenecho "c 字符串不为空"
elseecho "c 字符串为空"
fi
- source str.sh
4 文件测试
文件测试指的是根据给定的路径名称,判断对应的是文件还是目录,或者判断文件是否可读、可写、可执行等。
常用选项:
选项 | 说明 |
---|---|
-d | 测试是否为目录(Directory) |
-f | 测试是否为文件(File) |
-e | 测试目录或文件是否存在(Exist) |
-r | 测试当前用户是否有权限读取(Read) |
-w | 测试当前用户是否有权限写入(Write) |
-x | 测试是否设置有可执行(Excute)权限 |
# 检测文件是否存在
[ -e /test/helloworld.sh ]
# 检测文件是否具有可执行权限
[ -x /test/helloworld.sh ]
4.1 file命令
用于检测文件类型
tar zcvf num.tar.gz num.txt
file num.tar.gz
echo 123 > no.tar.gz
file no.tar.gz
5 数组
5.1 数组的定义
由多个元素之间以空格分隔的元素组成
数组的元素可使用的数据类型可以是:数字、“字符串”、‘字符串’
5.2 定义数组的方法
- 方法一
数组名=(值1 值2 值3 … )
# 创建数组
a=(1 2 3 4 5 6 7 8 9)
# 查看所有数组元素
echo ${a[@]}
- 方法二
数组名=([0]=值 [1]=值 [2]=值 …)
a=([0]=1 [1]=2 [2]=3)
echo ${a[@]}
- 方法三
列表名=“value0 value1 value2 …”
数组名=($列表名)
l="1 3 5 7 9"
a=($l)
echo ${a[@]}
- 方法四
数组名[0]=“value0”
数组名[1]=“value1”
数组名[2]=“value2”
…
a[0]=1
a[1]=3
a[2]=9
echo ${a[@]}
如果定义数组时没有按照顺序进行定义,空缺的默认为空,输出不显示,如
a=([1]=2 [3]=4 [5]=6)
echo ${a[@]}
5.3 数组的数据类型
数值类型:元素为数字
字符类型:元素为字符串,使用" "或’ '定义
a=(1 "b" 'c' )
echo ${a[@]}
5.4 数组的使用
5.4.1 获取数组所有元素
a=(1 3 5 7 9)
echo ${a[@]}
echo ${a[*]}
5.4.2 获取数组长度
实际上为所定义元素的个数,对于单个元素为元素长度
a=([1]=2 [3]=44 [5]=66)
echo ${#a[*]}
echo ${#a[3]}
5.4.3 获取元素索引值
a=(1 3 5 7 9)
echo ${#a[3]}
5.4.4 数组遍历
- vim test1.sh
#!/bin/bash
arr=(1 2 3 4 5)
for i in ${arr[*]}
doecho $i
done
5.4.5 数组切片
${数组名[@或*]:起始位置:长度}
a=(1 2 3 4 5 6 7 8 9)
echo ${a[@]:3:5}
5.4.6 数组字符替换
- 临时替换:不影响原数组
echo ${数组名[*]/被替换的字符或字段/新的字符或字段}
a=(1 2 3 4 5 6 7 8 9)
echo ${a[*]/4/dd}
echo ${a[*]}
- 永久替换:对变量重新赋值
数组名=(${数组名[*]/旧字符/新字符})
a=(1 2 3 4 5 6 7 8 9)
a=(${a[*]/4/d})
echo ${a[*]}
# 直接重新赋值也可以
a[5]=f
echo ${a[*]}
5.4.7 删除数组元素
- 删除数组的某个下标:unset 数组名[下标]
a=(1 2 3 4 5 6 7 8 9)
unset a[3]
- 删除数组:unset 数组名
a=(1 2 3 4 5 6 7 8 9)
unset a
5.4.8 数组追加元素
- 方法一:指定位置添加(已存在元素则替换)
array_name[index]=value
a=(1 2 3 4 5 6 7 8 9)
a[3]=0
echo ${a[*]}
- 方法二:末尾追加元素(不推荐)
array_name[${#array_name[@]}]=value
若数组元素不是按照顺序定义的会导致插入位置不准确
a=(1 2 3 4 5 6 7 8 9)
a[${#a[@]}]=a
echo ${a[*]}a=([1]=2 [3]=4 [5]=6)
a[${#a[@]}]=b
echo ${a[*]}
- 方法三:末尾追加多元素(推荐)
array_name=(“${array_name[@]}” value1 … valueN)
双引号不能省略,否则,当数组array_name中存在包含空格的元素时会按空格将元素拆分成多个
不能使用@,会将数组array_name中的所有元素作为一个元素添加到数组中。
a=(1 2 3 4 5 6 7 8 9)
a=("${a[@]}" a b c)
echo ${a[*]}
- 方法四
array_name+=(value1 … valueN)
a=(1 2 3 4 5 6 7 8 9)
a+=(aa bb cc)
echo ${a[*]}
5.4.9 向函数传数组参数
如果将数组变量作为函数参数,函数只会取数组变量的第一个值。
解决这个问题则需要将数组变量的值分解成单个的值,然后将这些值作为函数参数使用。在函数内部,再将所有的参数重新组合成一个新的数组变量。