Linux Shell编程 第4章 数组和函数

目录

 

数组

一、普通数组

二、关联数组

定义关联数组:

数组和循环

案例

案例1:while脚本快速定义数组

案例2:for脚本快速定义数组

案例3:数组统计性别

案例4:使用数组统计,用户shell的类型和数量

函数

一、定义函数

二、调用函数

三、示例

例1:初识函数

示例2:阶乘函数(传参)

优化

示例3:函数传参 数组传参

示例4:函数结果 赋予数组

影响Shell程序的内置命令

continue和break&shift

环境示例

主角1登场

主角2登场

主角3登场


 

数组

简介数组

变量:用一个固定的字符串,代替一个不固定字符串。

数组:用一个固定的字符串,代替多个不固定字符串。

类型

普通数组:只能使用整数作为数组索引

关联数组:可以使用字符串作为数组索引

终极图示

总结

变量切片有个索引的概念。一个索引(整数)对应一个字符。
普通数组:中的索引对应一个字符串。
关联数组:数组中的索引可以使用字符串。

一、普通数组

定义数组:

方法一: 一次赋一个值
数组名[下标]=变量值
# array1[0]=pear
# array1[1]=apple
# array1[2]=orange
# array1[3]=peach

查看数组
[root@localhost ~]# declare -a | grep array1
declare -a array1='([0]="pear" [1]="apache" [2]="orange" [3]="peach")'
查看数组
[root@localhost ~]# echo ${array1[@
]}
pear apache orange peach

方法二: 一次赋多个值
# array2=(tom jack alice)
# array3=(`cat /etc/passwd`) 希望是将该文件中的每一个行作为一个元数赋值给数组array3
# array4=(`ls /var/ftp/Shell/for*`)
# array5=(tom jack alice "bash shell")
# colors=($red $blue $green $recolor)
# array6=(1 2 3 4 5 6 7 "linux shell" [20]=saltstack)

访问数组元素:

访问数组元数:
# echo ${array1[0]} 访问数组中的第一个元数
# echo ${array1[@]} 访问数组中所有元数 等同于 echo ${array1[*]}
# echo ${#array1[@]} 统计数组元素的个数
# echo ${!array2[@]} 获取数组元素的索引
# echo ${array1[@]:1} 从数组下标1开始
# echo ${array1[@]:1:2} 从数组下标1开始,访问两个元素

二、关联数组

定义关联数组:

切记先声明关联数组

方法一: 一次赋一个值
数组名[索引]=变量值
 declare -A  ass_array1        // 声明关联数组
  ass_array1[index1]=pear
  ass_array1[index2]=apple
  ass_array1[index3]=orange
  ass_array1[index4]=peach

查看
[root@localhost ~]# echo ${ass_array1[@]}
peach pear apple orange


方法二: 一次赋多个值

[root@localhost ~]# declare -A ass_array2
[root@localhost ~]# ass_array2=([index1]=tom [index2]=jack [index3]=alice [index4]='bash shell')

查看数组:

[root@localhost ~]# echo ${ass_array2[@]}
bash shell tom jack alice

访问数组元素

[root@localhost ~]# echo ${ass_array2[index2]}     // 访问数组中的第二个元数
jack
[root@localhost ~]# echo ${ass_array2[*]}            //访问数组中所有元数 等同于 echo ${array1[@]}
bash shell tom jack alice   
[root@localhost ~]# echo ${ass_array2[@]}      //访问数组中所有元数 等同于 echo ${array1[*]}
bash shell tom jack alice
[root@localhost ~]# echo ${!ass_array2[@]}                // 获得数组元数的索引
index4 index1 index2 index3

数组和循环

1:通过循环定义和显示数组

2:通过数组统计数据

案例

案例1:while脚本快速定义数组

定义数组

#!/bin/bash
#循环读取文件,定义数组
while read line
do
#hosts:数组名
#[++i]:索引递增,++i是1开始,i++是0开始。
#$line:值,即文件中的内容
        hosts[++i]=$line
done < /etc/hosts

#输出索引每一行
for i in ${!hosts[@]}
do
echo "$i  :   ${hosts[$i]}"
done

测试数组

[root@localhost ~]# bash array1.sh
“数组hosts first:127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4”

1  :   127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
2  :   ::1         localhost localhost.localdomain localhost6 localhost6.localdomain6


案例2:for脚本快速定义数组

定义数组

[root@localhost ~]# vim for_array.sh 
#!/bin/bash
#2020
#for array
for line in `cat /etc/hosts`
do
        hosts[++i]=$line
done
for i in ${!hosts[@]}
do
echo "$i:  ${hosts[$i]}"
done

 

测试数组

[root@localhost ~]# bash for_array.sh 
1:  127.0.0.1
2:  localhost
3:  localhost.localdomain
4:  localhost4
5:  localhost4.localdomain4
6:  ::1
7:  localhost
8:  localhost.localdomain
9:  localhost6
10:  localhost6.localdomain6

 

区别

for的空格分割

解决方法:如何解决for的空格分割的问题。使用IFS=$’\n’  重新定义分隔符。
另外,如果脚本中还有for怎么办呢?储存变量,还原变量

解决示例

案例3:数组统计性别

1 定义性别文件

[root@localhost ~]# vim sex.txt
jack m
alice f
tom m

2 定义脚本统计性别

#!/bin/bash
declare -A sex
while read line
do
        type=`echo $line|awk '{print $2}'`
        let sex[$type]++
done < sex.txt

for i in ${!sex[@]}
do
        echo "$i : ${sex[$i]}"
done

3 测试脚本

[root@localhost ~]# bash sex.sh 
f : 1
m : 2

案例4:使用数组统计,用户shell的类型和数量

示例

declare -A shells
while read ll
do
type=`echo $ll | awk -F:  '{print $NF}'`
let shells[$type]++
done  < /etc/passwd

for i in ${!shells[*]}
do
echo "$i: ${shells[$i]}"

done

验证结果

[root@localhost ~]# bash  shells.sh
/sbin/nologin: 20
/bin/sync: 1
/bin/bash: 4
/sbin/shutdown: 1
/sbin/halt: 1

 

函数

概述

函数是一段完成特定功能的代码片段(块)
在shell中定义了函数,就可以使代码模块化,便于复用代码
注意函数必须先定义才可以使用。

重点

传参 $1,$2
局部变量 local
返回值 return   即$?

一、定义函数

方法一:
函数名() {
函数要实现的功能代码
}

方法二

function 函数名 {
函数要实现的功能代码
}

二、调用函数

语法

函数名
函数名 参数1 参数2

三、示例

例1:初识函数

需求

编写循环脚本,功能菜单 
provide these tools:
 show disk info(d)
 show mem info(m)
 show cpu info(c)
 quit(q)

思路

1 编写菜单和判断.

2 添加循环

3 添加函数

#!/bin/bash
show_menu() {
cat << EOF
provide these tools:
 show disk info(d)
 show mem info(m)
 show cpu info(c)
 quit(q)
EOF
}

while :
do

show_menu
read -p "Input choice: " choice
        case $choice in
                d)
                        echo "===========disk info=============="
                        df -hT
                        ;;
                m)
                        echo "==========meme info==============="
                        free -m
                        ;;
                c)
                        echo "==========cpu info================="
                        uptime
                        ;;
                q)
                        break
                        ;;
                *)
                        show_menu
                        ;;
        esac
done

效果:

 

示例2:阶乘函数(传参)

需求:制作函数用于阶乘

思路

1 了解阶乘概念

1*2*3*4*5=120

[root@localhost ~]# let aa=1*2*3*4*5;echo $aa
120

2 定义函数

3 引用函数

演示

#!/bin/bash
#定义函数名fun1
fun1() {
#定义阶乘元数
factorial=1
#使阶乘循环
for((i=1;i<=5;i++))
do
#阶乘公式
factorial=$[$factorial*$i]
done
#输出阶乘结果
echo “5的阶乘是:$factorial”
}
fun1

优化

优化1:传参,让函数能够自定义

 

#!/bin/bash
fun1() {
factorial=1
for((i=1;i<=$1;i++))
do
factorial=$[$factorial*$i]
done
echo “$1的阶乘是:$factorial”
}

fun1  3
测试脚本

优化2:传参2,由脚本外部传递参数。

#!/bin/bash
fun1() {
factorial=1
for((i=1;i<=$1;i++))
do
factorial=$[$factorial*$i]
done
echo “$1的阶乘是:$factorial”
}

fun1 $1
fun1 $2
fun1 $3

测试:
[root@localhost ~]# bash cc.sh 3 5 10
“3的阶乘是:6”
“5的阶乘是:120”
“10的阶乘是:3628800”

 

 提示·:函数传参能够在模块化的命令集中,添加自定义部分。参数应加在调用函数的后面。
shell脚本的参数与函数参数不同。是先将SHELL的参数传给函数,函数本身再转换到内部。

优化3:shell 的写法和其他运算表达式。

#!/bin/bash
fun1() {
factorial=1
#for((i=1;i<=$1;i++))
for i in `seq $1`
do
#factorial=$[$factorial*$i]
#let factorial=$factorial*$i
let factorial*=$i
done
echo “$1的阶乘是:$factorial”
}

fun1  $1

fun1  $2
fun1  $3

 

测试

示例3:函数传参 数组传参

1 制作一个简单的阶乘脚本。通过数组给函数传参

#!/bin/bash
    #1 先定义一个数组
num=(1 2 3)
    #2 定义一个函数
array(){
factorial=1
for i in $*     #(重点2)
do
    #定义阶层的公式
factorial=$[factorial * $i]
done
echo $factorial
}
    #调用函数使用数组(重点1)
array ${num[*]}

2 测试成功。

 

3 数组的好处在于,多个数组时传参的效率就增高了。

4 测试结果即可。谢谢观赏。

示例4:函数结果 赋予数组

场景:用户获赠流量包(每人增加5G),结果运算

1 通过函数输出到数组

#!/bin/bash
num=(1 2 3)
array(){
        #local定义变量仅在函数中有效。
        local j
        #设置循环的次数,等于索引总数。
                for i in  $*
                do
                #定义不同的值乘以5.注意调取值的时候使用的是索引。
                        outarray[j++]=$[$i+5]

                done
        #输出新的数组。
        echo "${outarray[*]}"
}
result=`array ${num[*]}`
echo ${result[*]}

2 测试脚本成功。

[root@localhost ~]# bash function_array.sh 
5 10 15

总结:函数不仅可以从数组中调取值,
还可以赋予数组值。

影响Shell程序的内置命令

概览


:
true
false
exit
break
continue
shift
————————————————————————

shift 使位置参数向左移动,默认移动1位,可以使用shift 2
exit 退出整个程序
break 结束当前循环,或跳出本层循环
continue 忽略本次循环剩余的代码,直接进行下一次循环


continue和break&shift

环境示例

需求

1 通过循环脚本,输出如下效果。

  A123456789
  B123456789
...
  D123456789

2 编写循环脚本。

#!/bin/bash
for i in {A..D}
do
        echo $i
        for j in {1..9}
        do
                echo $j
        done
done

3 测试脚本,观察结果(满意否)

[root@localhost ~]# bash for1.sh
A
1
2
3
4
5
6
7
8
9
B

因为默认echo输出换行符,使用-n不输出

 

4 解决换行问题

#!/bin/bash
for i in {A..D}
do
        echo -n $i
        for j in {1..9}
        do
                echo -n $j
        done
done

5 测试脚本,观察结果(满意否)

[root@localhost ~]# bash for1.sh
A123456789B123456789C123456789D123456789

还不是很满意

6 外循环,添加一条空行语句。

#!/bin/bash
for i in {A..D}
do
        echo -n $i
        for j in {1..9}
        do
                echo -n $j
        done
#空行
        echo 
done

7 再次测试。完成预期

[root@localhost ~]# bash for1.sh
A123456789
B123456789
C123456789
D123456789

8 总结:循环嵌套的规则是:外部循环一次,内部循环全部。

主角1登场

9 需求:跳出关于5的循环。

[root@localhost ~]# bash for1.sh
A12346789
B12346789
C12346789
D12346789

10  continue登场

if 判断此次循环是否为5,
continue 跳过本次循环。

#!/bin/bash
for i in {A..D}
do
        echo -n $i
        for j in {1..9}
        do
                if [ $j -eq 5 ];then
                continue
                fi
                echo -n $j
        done
        echo 
done

测试

[root@localhost ~]# bash for1.sh
A12346789
B12346789
C12346789
D12346789

主角2登场

11 换成break会怎么样呢?

#!/bin/bash
for i in {A..D}
do
        echo -n $i
        for j in {1..9}
        do
                if [ $j -eq 5 ];then
                break 2
                fi
                echo -n $j
        done
        echo 
done

12 测试

[root@localhost ~]# bash for1.sh
A1234

主角3登场

shift 移动参数

1 for 循环不定义循环范围,循环取参数作为循环范围。

#!/bin/bash
for i
do
        let sum+=$i
done
echo "sum : $sum"

测试:

[root@localhost ~]# bash sum.sh 
sum : 
[root@localhost ~]# bash sum.sh 1
sum : 1
[root@localhost ~]# bash sum.sh 2
sum : 2
[root@localhost ~]# bash sum.sh 3
sum : 3
[root@localhost ~]# bash sum.sh 1 3
sum : 4

2 使用while循环,发现停不下来

#!/bin/bash
while [ $# -ne 0 ]
do
        let sum+=$1
        echo $sum
done
echo "sum : $sum"

测试

[root@localhost ~]# bash sum.sh 1 2
根本停不下来。因为循环为真。

3 使用shift 移动参数的命令。结果得以实现。

#!/bin/bash
while [ $# -ne 0 ]
do
        let sum+=$1
        shift
done
echo "sum : $sum"

测试:

[root@localhost ~]# bash sum.sh 1 2
sum : 3
[root@localhost ~]# bash sum.sh 1 2 3
sum : 6

4 另一个,创建用户的案例。理解参数位移

#!/bin/bash
while [ $# -ne 0 ]
do
        useradd $1
        echo "$1 is created"
        shift
done

测试

[root@localhost ~]# bash shift_user.sh aa bb
aa is created
bb is created

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值