7.9 范例
范例:生成10个随机数保存于数组中,并找出其最大值和最小值
[root@rocky8 ~]# vim max_min.sh
#!/bin/bash
#
#**********************************************************************************************
#Author: Raymond
#QQ: 88563128
#Date: 2021-10-22
#FileName: max_min.sh
#URL: raymond.blog.csdn.net
#Description: The test script
#Copyright (C): 2021 All rights reserved
#*********************************************************************************************
declare -i min max
declare -a nums
for ((i=0;i<10;i++));do
nums[$i]=$RANDOM
[ $i -eq 0 ] && min=${nums[0]} && max=${nums[0]} && continue
[ ${nums[$i]} -gt $max ] && max=${nums[$i]} && continue
[ ${nums[$i]} -lt $min ] && min=${nums[$i]}
done
echo "All numbers are ${nums[*]}"
echo Max is $max
echo Min is $min
[root@rocky8 ~]# bash max_min.sh
All numbers are 11268 31340 1794 24730 32582 4141 21637 25521 22265 12240
Max is 32582
Min is 1794
范例:编写脚本,定义一个数组,数组中的元素对应的值是/var/log目录下所有以.log结尾的文件;统计出其下标为偶数的文件中的行数之和
[root@rocky8 ~]# vim array.sh
#!/bin/bash
#
#**********************************************************************************************
#Author: Raymond
#QQ: 88563128
#Date: 2021-10-22
#FileName: array.sh
#URL: raymond.blog.csdn.net
#Description: The test script
#Copyright (C): 2021 All rights reserved
#*********************************************************************************************
declare -a files
files=(/var/log/*.log)
declare -i lines=0
for i in $(seq 0 $[${#files[*]}-1]); do
if [ $[$i%2] -eq 0 ];then
let lines+=$(wc -l ${files[$i]} | cut -d' ' -f1)
fi
done
echo "Lines: $lines"
[root@rocky8 ~]# bash array.sh
Lines: 1311
7.10 练习
- 输入若干个数值存入数组中,采用冒泡算法进行升序或降序排序
- 将下图所示,实现转置矩阵 matrix.sh
1 2 3 1 4 7
4 5 6 ===> 2 5 8
7 8 9 3 6 9 - 打印杨辉三角形
8.字符串处理
8.1 字符串切片
基于偏移量取字符串
#返回字符串变量var的长度,一个汉字也算一个
${#var}
#返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始,到最后的部分,offset的取值在0 到 ${#var}-1 之间(bash4.2后,允许为负值)
${var:offset}
#返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始,长度为number的部分
${var:offset:number}
#取字符串的最右侧几个字符,取字符串的最右侧几个字符, 注意:冒号后必须有一空白字符
${var: -length}
#从最左侧跳过offset字符,一直向右取到距离最右侧lengh个字符之前的内容,即:掐头去尾
${var:offset:-length}
#先从最右侧向左取到length个字符开始,再向右取到距离最右侧offset个字符之间的内容,注意:-length前空格,并且length必须大于offset
${var: -length:-offset}
范例:
[root@rocky8 ~]# alpha=`echo {a..z}|tr -d ' '`
[root@rocky8 ~]# echo $alpha
abcdefghijklmnopqrstuvwxyz
[root@rocky8 ~]# echo ${#alpha}
26
[root@rocky8 ~]# echo ${alpha:10} #跳过前10个
klmnopqrstuvwxyz
[root@rocky8 ~]# echo ${alpha:10:6} #跳过前10个取6个
klmnop
[root@rocky8 ~]# echo ${alpha:-6}
abcdefghijklmnopqrstuvwxyz #-6 前边不加空格不起作用
[root@rocky8 ~]# echo ${alpha: -6} #倒数6个
uvwxyz
[root@rocky8 ~]# echo ${alpha: -6:3} #倒数6个中的前3个
uvw
[root@rocky8 ~]# echo ${alpha:6:-5} #掐头去尾
ghijklmnopqrstu
[root@rocky8 ~]# echo ${alpha: -6:-5} #倒数6个,跳过倒数5个
u
基于模式取子串
#其中word可以是指定的任意字符,自左而右,查找var变量所存储的字符串中,第一次出现的word, 删除字符串开头至第一次出现word字符串(含)之间的所有字符,即懒惰模式,以第一个word为界删左留右
${var#*word}:
#同上,贪婪模式,不同的是,删除的是字符串开头至最后一次由word指定的字符之间的所有内容,即贪婪模式,以最后一个word为界删左留右
${var##*word}:
范例:
[root@rocky8 ~]# file="var/log/messages"
[root@rocky8 ~]# echo ${file#*/}
log/messages
[root@rocky8 ~]# echo ${file##*/}
messages
[root@rocky8 ~]# url=http://www.raymond.com/index.html
[root@rocky8 ~]# echo ${url#*/}
/www.raymond.com/index.html
[root@rocky8 ~]# echo ${url##*/}
index.html
#其中word可以是指定的任意字符,功能:自右而左,查找var变量所存储的字符串中,第一次出现的word,删除字符串最后一个字符向左(向前)至第一次出现word字符串(含)之间的所有字符,即懒惰模式,以从右向左的第一个word为界删右留左
${var%word*}
#同上,只不过删除字符串最右侧的字符向左至最后一次出现word字符之间的所有字符,即贪婪模式,以从右向左的最后一个word为界删右留左
${var%%word*}
范例:
[root@rocky8 ~]# echo ${file%/*}
var/log
[root@rocky8 ~]# echo ${file%%/*}
var
[root@rocky8 ~]# echo ${url%%/*}
http:
[root@rocky8 ~]# url=http://www.raymond.com:8080
[root@rocky8 ~]# echo ${url%%:*}
http
[root@rocky8 ~]# echo ${url##*:}
8080
8.2 查找替换
#查找var所表示的字符串中,第一次被pattern所匹配到的字符串,以substr替换之
${var/pattern/substr}
#查找var所表示的字符串中,所有能被pattern所匹配到的字符串,以substr替换之
${var//pattern/substr}
#查找var所表示的字符串中,行首被pattern所匹配到的字符串,以substr替换之
${var/#pattern/substr}
#查找var所表示的字符串中,行尾被pattern所匹配到的字符串,以substr替换之
${var/%pattern/substr}
范例:
[root@rocky8 ~]# echo ${url/:/+/}
http+///www.raymond.com:8080
[root@rocky8 ~]# echo ${url//:/+/}
http+///www.raymond.com+/8080
[root@rocky8 ~]# getent passwd root
root:x:0:0:root:/root:/bin/bash
[root@rocky8 ~]# line=`getent passwd root`
[root@rocky8 ~]# echo $line
root:x:0:0:root:/root:/bin/bash
[root@rocky8 ~]# echo ${line/#root/admin/}
admin/:x:0:0:root:/root:/bin/bash
[root@rocky8 ~]# line1=1:`getent passwd root`
[root@rocky8 ~]# echo $line1
1:root:x:0:0:root:/root:/bin/bash
[root@rocky8 ~]# echo ${line1/#root/admin/}
1:root:x:0:0:root:/root:/bin/bash
# #号是以什么开头
[root@rocky8 ~]# echo ${line/%bash/nologin/}
root:x:0:0:root:/root:/bin/nologin/
# % 以什么结尾
8.3 查找并删除
#删除var表示的字符串中第一次被pattern匹配到的字符串
${var/pattern}
#删除var表示的字符串中所有被pattern匹配到的字符串
${var//pattern}
#删除var表示的字符串中所有以pattern为行首匹配到的字符串
${var/#pattern}
#删除var所表示的字符串中所有以pattern为行尾所匹配到的字符串
${var/%pattern}
范例:
[root@rocky8 ~]# echo ${line/root/}
:x:0:0:root:/root:/bin/bash
[root@rocky8 ~]# echo ${line//root/}
:x:0:0::/:/bin/bash
8.4 字符大小写转换
#把var中的所有小写字母转换为大写
${var^^}
#把var中的所有大写字母转换为小写
${var,,}
范例:
[root@rocky8 ~]# echo ${line^^} #^^ 转换成大写
ROOT:X:0:0:ROOT:/ROOT:/BIN/BASH
[root@rocky8 ~]# LINE=`echo ${line^^}`
[root@rocky8 ~]# echo $LINE
ROOT:X:0:0:ROOT:/ROOT:/BIN/BASH
[root@rocky8 ~]# echo ${LINE,,} #,, 转换成小写
root:x:0:0:root:/root:/bin/bash
9.高级变量
9.1 高级变量赋值
范例:
[root@rocky8 ~]# unset name;cto=${name-'raymond'};echo $cto
raymond
[root@rocky8 ~]# name="";cto=${name-'raymond'};echo $cto
[root@rocky8 ~]# name="boss";cto=${name-'raymond'};echo $cto
boss
[root@rocky8 ~]# unset name;cto=${name:-'raymond'};echo $cto
raymond
[root@rocky8 ~]# name="";cto=${name:-'raymond'};echo $cto
raymond
[root@rocky8 ~]# name="boss";cto=${name:-'raymond'};echo $cto
boss
9.2 高级变量用法-有类型变量
Shell变量一般是无类型的,但是bash Shell提供了declare和typeset两个命令用于指定变量的类型,两个命令是等价的
declare [选项] 变量名
选项:
-r 声明或显示只读变量
-i 将变量定义为整型数
-a 将变量定义为数组
-A 将变量定义为关联数组
-f 显示已定义的所有函数名及其内容
-F 仅显示已定义的所有函数名
-x 声明或显示环境变量和函数,相当于export
-l 声明变量为小写字母 declare -l var=UPPER
-u 声明变量为大写字母 declare -u var=lower
范例:
[root@rocky8 ~]# declare -l name=BOSS
[root@rocky8 ~]# echo $name
boss
[root@rocky8 ~]# declare -u name=boss
[root@rocky8 ~]# echo $name
BOSS
9.3 变量间接引用
9.3.1 eval命令
eval命令将会首先扫描命令行进行所有的置换,然后再执行该命令。该命令适用于那些一次扫描无法实现其功能的变量,该命令对变量进行两次扫描
范例:
[root@rocky8 ~]# echo $name
BOSS
[root@rocky8 ~]# CMD=whoami
[root@rocky8 ~]# echo $CMD
whoami
[root@rocky8 ~]# eval $CMD #eval 两次扫描,第一次,变量替换,第二次执行替换后的结果
root
[root@rocky8 ~]# n=10;for i in {1..$n};do echo $i; done
{1..10}
[root@rocky8 ~]# n=10;for i in `eval echo {1..$n}`;do echo $i; done
1
2
3
4
5
6
7
8
9
10
[root@rocky8 ~]# i=1
[root@rocky8 ~]# j=a
[root@rocky8 ~]# $j$i=hello
-bash: a1=hello: command not found
[root@rocky8 ~]# eval $j$i=hello
[root@rocky8 ~]# echo $j$i
a1
[root@rocky8 ~]# echo $a1
hello
9.3.2 间接变量引用
如果第一个变量的值是第二个变量的名字,从第一个变量引用第二个变量的值就称为间接变量引用variable1的值是variable2,而variable2又是变量名,variable2的值为value,间接变量引用是指通过variable1获得变量值value的行为
variable1=variable2
variable2=value
bash Shell提供了两种格式实现间接变量引用
#方法1
#变量赋值
eval tempvar=\$$variable1
#显示值
eval echo \$$variable1
eval echo '$'$variable1
#方法2
#变量赋值
tempvar=${!variable1}
#显示值
echo ${!variable1}
范例:
[root@rocky8 ~]# x=y
[root@rocky8 ~]# y=100
[root@rocky8 ~]# echo $x
y
[root@rocky8 ~]# eval echo \$$x
100
[root@rocky8 ~]# eval echo $$x
2417x
[root@rocky8 ~]# echo $$
2417
[root@rocky8 ~]# echo ${!x}
100
范例: 批量创建用户
[root@rocky8 ~]# vim eval_createuser.sh
#!/bin/bash
#
#**********************************************************************************************
#Author: Raymond
#QQ: 88563128
#Date: 2021-10-22
#FileName: eval_createuser.sh
#URL: raymond.blog.csdn.net
#Description: The test script
#Copyright (C): 2021 All rights reserved
#*********************************************************************************************
n=$#
[ $n -eq 0 ] && { echo "Usage: `basename $0` username..." ; exit 2; }
for i in `eval echo {1..$n}`;do
user=${!i}
id $user &> /dev/null && echo $user is exist || { useradd $user; echo $user is created; }
done
[root@rocky8 ~]# bash eval_createuser.sh tom jack bob
tom is created
jack is created
bob is created