# 变量的高级用法
# 变量的删除使用unset 变量
语法 | 说明 |
---|---|
unset -v var | 删除变量 var (默认,可以不加-v) |
unset -f func | 删除函数 func |
# 变量替换和测试
语法 | 说明 |
---|---|
${变量名#匹配规则} | 从变量 开头 进行规则匹配,将符合 最短 匹配长度的数据进行删除 |
${变量名##匹配规则} | 从变量 开头 进行规则匹配,将符合 最长 匹配长度的数据进行删除 |
${变量名%匹配规则} | 从变量 尾部 进行规则匹配,将符合 最短 匹配长度的数据进行删除 |
${变量名%%匹配规则} | 从变量 尾部 进行规则匹配,将符合 最长 匹配长度的数据进行删除 |
${变量名/旧字符串/新字符串} | 变量内容符合旧字符串规则,则 第一个 旧字符串会被新字符串替代 |
${变量名//旧字符串/新字符串} | 变量内容符合旧字符串规则,则 全部的 旧字符串会被新字符串替代 |
var="i love you,do you love me"
var1=${var#*ov}
echo $var1 # e you,do you love me
var2=${var##*ov}
echo $var2 # e me
var3=${var%ov*}
echo $var3 # i love you,do you l
var4=${var/e/E}
echo $var4 # i lovE you,do you love me
var5=${var//e/E}
echo $var5 # i lovE you,do you lovE mE
var6=${var/*ov/OV}
echo $var6 # OVe me
# 字符串处理
- macOS 中 expr 的大批无法实现
# 计算字符串长度
方式 | 语法 | 说明 |
---|---|---|
方式 1 | ${#string} | string 是变量 |
方式 2 | expr length "$string" | string 有空格,必须加双引号(该方法在 macOS 上不成功) |
var="hello world"
len1=${#var}
echo $len1
# 获取字串(字符)在字符串中的索引位置
方式 | 语法 | 说明 |
---|---|---|
方式 1 | expr index $string substring | 查找 substring 是按照 substring 里面的每一个字符在$string 里面去匹配的 |
# 获取字符串中字串的长度
方式 | 语法 | 说明 |
---|---|---|
方式 1 | expr match $string substr | 必须从$string 头开始匹配 |
# 抽取字串
- expr/从右开始匹配 下标从 1 开始计算,其余从 0 开始
方式 | 语法 | 说明 |
---|---|---|
方式 1 | ${string:position} | 从 string 的 position 开始 |
方式 2 | ${string:position:length} | 从 string 的 position 开始,匹配长度为 length |
方式 3 | ${string: -position} | 从 string 的 右边 开始匹配 -号前面有空格 |
方式 4 | ${string:(position)} | 从 string 的 左边 开始匹配 |
方式 5 | expre substr $string $position $length | 从 string 的 position 开始,匹配长度为 length |
var1="kafka hadoop yarn mapreduce"
substr1=${var1:10}
substr2=${var1:10:6}
substr3=${var1: -5}
substr4=${var1: -10:4}
echo $substr1 # op yarn mapreduce
echo $substr2 # op yar
echo $substr3 # educe
echo $substr4 # map
# 练习
#!/bin/bash
#
string="Bigdata process framework is Hadoop,Hadoop is an open source project"
function print_tips() {
echo "******************************"
echo "(1) 打印string长度"
echo "(2) 删除字符串中所有的Hadoop"
echo "(3) 替换第一个Hadoop为Mapreduce"
echo "(4) 替换全部Hadoop为Mapreduce"
echo "******************************"
}
function len_of_string() {
echo "${#string}"
}
function del_hadoop() {
echo "${string//Hadoop/}"
}
function rep_hadoop_mapreduce_first() {
echo "${string/Hadoop/Mapreduce}"
}
function rep_hadoop_mapreduce_all() {
echo "${string//Hadoop/Mapreduce}"
}
while true; do
echo "【string=$string】"
print_tips
read -p "Pls input your choice(1|2|3|4|q|Q): " choice
case $choice in
1)
len_of_string
break
;;
2)
del_hadoop
break
;;
3)
rep_hadoop_mapreduce_first
break
;;
4)
rep_hadoop_mapreduce_all
break
;;
q | Q)
exit
;;
*)
echo "Error,input only in {1|2|3|4|q|Q}"
;;
esac
done
# 命令替换
$(command)
表示命令替换$(())
主要用来进行整数运算,包括加减乘除,引用变量前面可以加$,也可以不加$`和$()两者是等价的,但推荐初学者使用$(),易于掌握;缺点是极少数 UNIX 可能不支持,但`都是支持的
# 定义
某一段命令的结果作为另一个命令的一部分
# 语法
方式 | 语法 |
---|---|
方式一 | `command` |
方式二 | $(command) |
echo "This is $(date +%Y) year"
echo "This is $(($(date +%Y) + 1)) year"
date +%j
echo "This year have passed $(date +%j) days"
echo "This year have passed $(($(date +%j) / 7)) weeks"
echo "There is $((365 - $(date +%j))) days before new year"
echo "There is $(((365 - $(date +%j)) / 7)) weeks before new year"
# 判定nginx进程是否存在,若不存在则自动拉起该进程
nginx_process_num=$(ps -ef | grep nginx | grep -v grep | wc -l)
if [ $nginx_process_num -eq 0 ]; then
systemctl start nginx
fi
# 有类型变量
shell
本身是弱类型的,但是也可以申明类型,通过declare
和typeset
命令
# declear 参数命令表
参数 | 含义 |
---|---|
-r | 将变量设为只读 |
-i | 将变量设为整数 |
-a | 将变量定义为数组 |
-f | 显示系统定义过的所有函数及内容 |
-F | 仅显示系统定义过的函数名 |
-x | 将变量声明为环境变量 |
- 如果没有声明环境变量当前变量只对当前终端有效,声明成为环境变量在当前终端下的任意脚本里可以获取值,跨终端依旧不行
num1=2001
num2=$num1+1
echo $num2 # 2001+1
declare -i num2
num2=$num1+1
echo $num2 # 2002
# 取消声明变量
declare +r var
declare +i var
declare +a var
declare +x var
# 数组的基本操作
不推荐在 shell 中频繁地使用数组
数组下标从 0 开始
常用操作 | 操作命令 |
---|---|
打印元素 | echo ${array[2]} |
打印所有元素 | echo ${array[@]} |
打印元素的个数 | echo ${#array[@]} / ${#array[*]} |
打印元素长度 | echo ${#array[3]} |
给元素赋值 | array[3]="Li" |
删除元素/数组 | unset array[2](注意删除了之后数组内每个元素下标是不会变的)(Macos 无效);unset array |
分片访问 | echo ${array[@]:1:3} |
元素内容替换 | ${array[@]/e/E} 只替换第一个e;${array[@]//e/E} 替换所有的 e |
# 数组的声明
- 是以()包裹,每个下标用空格切分而不是逗号
array=("Allen" "Mike" "Messi" "Jerry" "Hanmeimei" "Wang")
declare -a array=("jones" "mike" "kobe" "jordan")
echo $array # jones
# 输出数组内容
echo ${array[@]} # 输出全部内容
echo ${array[1]} # 输出下标索引为1的内容
# 输出数组长度
echo ${#array[@]} # 数组内元素个数
echo ${#array[0]} # 数组内下标索引为0的元素长度
# 给数组某个下标赋值
array[0]="lily" # 给数组下标索引为1的元素赋值为lily
array[20]="hanmeimei" # 在数组尾部添加一个新元素
# 删除元素
unset array[2] # 清除元素
unset array # 清空整个数组
# 分片访问
${array[@]:1:3} # mike kobe jordan 显示数组下标索引从1开始到3的3个元素,不显示索引为4的元素
${array[@]:1} # 显示数组下标索引从1到最后
# 内容替换
${array[@]/an/AN} # 将数组中所有元素内包含kobe的子串替换为mcgrady
${array[@]/e/E} # 将数组中所有元素第一个小写e变为大写E
${array[@]//e/E} # 将数组中所有元素全部小写e变为大写E
# 数组遍历
for v in ${array[@]}
do
echo $v
done
# bash 数学运算之 expr
只支持整数运算
操作符之间要留空格
该操作只能精确到整数,浮点数无效
操作符很多设计关键字,需要转义\
expr $num1 + $num2 # 正确
expr $num1+$num2 # 错误
# 语法格式
方式 | 语法 |
---|---|
方式 1 | expr $num1 operator $num2 |
方式 2 | $(($num1 operator $num2)) |
expr 直接在命令行中写会直接输出,而$(())的方式则需要赋值变量才行
$(())的方式语法不用那么严谨,变量不一定要加$,运算符余变量之间也可以没有空格。运算符也不需要转义
$(())的方式只能进行加减乘除商
# 操作符对照表
操作符 | 含义 |
---|---|
num1 | num2 | num1 不为空且非 0,返回 num1,否则返回 num2 |
num1 & num2 | num1 不为空且非 0,返回 num1,否则返回 0 |
num1 < num2 | num1 小于 num2,返回 1,否则返回 0 |
num1 <= num2 | num1 小于等于 num2,返回 1,否则返回 0 |
num1 = num2 | num1 等于 num2,返回 1,否则返回 0 |
num1 != num2 | num1 不等于 num2,返回 1,否则返回 0 |
num1 > num2 | num1 大于 num2,返回 1,否则返回 0 |
num1 >= num2 | num1 大于等于 num2,返回 1,否则返回 0 |
num1 +-*%/ num2 | num1 对 num2 求和差乘余商 |
num1=20
num2=100
expr $num1 \| $num2
expr $num1 \& $num2
expr $num1 \< $num2
expr $num1 \< $num2
expr $num1 \<= $num2
expr $num1 \> $num2
expr $num1 \>= $num2
expr $num1 = $num2
expr $num1 != $num2
expr $num1 + $num2
expr $num1 - $num2
expr $num1 \* $num2
expr $num1 / $num2
expr $num1 % $num2
# 练习
输入一个正整数,计算 1+2+..输入值的和,验证是否为正整数
tips:
判断一个树是否为正整数的方式为$num1 + 1,然后去echo $? 是否为 0
while true; do
read -p "Pls enter a positive integer(num>0): " num
expr $num + 1 &>/dev/null
if [ $? -ne 0 ]; then # 注意这个条件要单独分离以防使用&&>0的时候导致报错
echo "Error,You must input a interger"
continue
else
if [ $(expr $num \> 0) -ne 1 ]; then
echo "Error,You must input a postive integer"
continue
else
sum=0
for ((i = 0; i <= $num; i++)); do
sum=$(expr $sum + $i) # 注意这里赋值要使用sum表示覆盖这个变量而不能使用$sum
done
echo "1+2+3+4+5+...+$num=$sum"
fi
fi
done
# bc
- bc 是 bash 内置的运算器,支持浮点运算
# 操作符对照表
操作符 | 含义 |
---|---|
num1 +-*%/ num2 | num1 对 num2 求和差乘余商 |
num1 ^ num2 | 指数运算 |
# 进入 bc 界面使用
bc
23 / 5
4
23 % 5
3
scale=2 # 设置保留位数
23/5
4.60
# 在命令行或脚本中使用
echo "23/5" | bc # 4
echo "scale=4;23/5" | bc # 4.6000