39.第六章 Shell脚本编程高级进阶(四)

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 练习

  1. 输入若干个数值存入数组中,采用冒泡算法进行升序或降序排序
  2. 将下图所示,实现转置矩阵 matrix.sh
    1 2 3 1 4 7
    4 5 6 ===> 2 5 8
    7 8 9 3 6 9
  3. 打印杨辉三角形

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 高级变量赋值

39.第六章 Shell脚本编程高级进阶(四)
范例:

[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
上一篇:39_面向对象_Trait和抽象类的区别


下一篇:第39篇-Java通过JNI调用C/C++函数