内容目录

shell函数

什么是shell函数

  • 函数其实就是一堆命令的合集,用来完成特定功能的代码块

为何需要函数

  • 比如:我们经常需要使用判断功能,完全可以将其封装为一个函数,这样在写程序过程中可以在任何地方调用该函数,不必重复编写
    • 函数能减少代码冗余,增加代码的可读性
    • 函数和变量类似,必须先定义才可以调用,如果定义不调用则不会被执行

函数基础语法

  1. 定义shell函数,可以通过如下两种方式进行定义
# 方式一
name()
{
    command1
    command2
    ...
    commandn
}

# 方式二
function name
{
    command1
    command2
    ...
    commandn
}
  1. 调用函数,直接使用函数名调用。(可以理解为shell的一条命令)
fun() { echo "hello world"; }

# 调用函数
fun
hello world

函数参数传递

在函数内部可以使用参数$1、$2...,调用函数function_name $1 $2 ...

  1. 函数中传递单个参数示例
fun() { echo "hello,$1"; }

# 调用
fun monday
hello,monday
  1. 函数中传递多个参数示例
fun() { echo "hello,$1 $2 $3"; }
fun linux shell python
hello,linux shell python
  1. 函数中传递多个参数,$*接收所有的参数传递
fun() { echo "hello,$*"; }
fun monday tuesday wednesday thursday friday saturday sunday
hello,monday tuesday wednesday thursday friday saturday sunday

函数实现计算器功能脚本

  • 需求:写一个脚本,该脚本可以实现计算器的功能,可以进行+-*/四周计算
    • sh cal.sh 40 + 30
    • sh cal.sh 40 - 30
    • sh cal.sh 40 * 30
    • sh cal.sh 40 / 30
cat cal.sh
#!/usr/bin/bash

calsum() {
        case $2 in
        +)
                echo "$[ $1 + $3 ]"
                ;;
        -)
                echo "$[ $1 - $3 ]"
                ;;
        x)
                echo "$[ $1 * $3 ]"
                ;;
        /)
                echo "$[ $1 / $3 ]"
                ;;
        esac
}
#调用函数并进行参数传递
calsum $1 $2 $3

函数实现nginx启停脚本

需求:写一个脚本,实现nginx服务的启动、停止、重启

cat nginx.sh
#!/usr/bin/bash
. /etc/init.d/functions

#定义函数,函数需要传递一个参数
nginx_when() {
        if [ $? -eq 0 ];then
                action "nginx $1 is ok!" /bin/true
        else
                action "nginx $1 is error..." /bin/false
        fi
}

#接收脚本传入的第一个位置参数,然后进行匹配
case $1 in
        start)
                nginx
                nginx_when $1
                ;;
        stop)
                nginx -s stop
                nginx_when $1
                ;;
        reload)
                nginx -s reload
                nginx_when $1
                ;;
        *)
                echo "USAGE: $0 { start|stop|reload }"
esac

函数状态返回值

  • shell的函数返回值,也算是退出的状态,在shell中只有echo、return两种方式
    • return返回值:只能返回1-255的整数,函数使用return返回值,通常只是用来供其他地方调用获取状态,因此通常仅返回0或1;0表示成功,1表示失败。
    • echo返回值:使用echo可以返回任何字符串结果,通常用于返回数据,比如一个字符串值或者列表值
echo数据返回示例
cat echo.sh
#!/usr/bin/bash

get_users() {
        users=$(cat /etc/passwd | awk -F ':' '{print $1}')
        echo $users
}
#get_users

#可以对拿到的函数结果进行遍历
index=1
for u in $(get_users)
do
        echo "the $index user is :$u"
        let index++
done

shell数组

什么是数组

  • 数组其实也是变量,传统的变量只能存储一个值,但数组可以存储多个值

数组的分类

  • shell数组分为普通数组和关联数组
    • 普通数组:只能使用整数作为数组索引
    • 关联数组:可以使用字符串作为数组索引

普通数组:books=(linux nginx shell)

linux nginx shell
0 1 2

普通数组下标只能是整数

关联数组:info=([name]=xiaoming [age]=18 [skill]=linux)

xiaoming age linux
name age skill

关联数组的下标可以是字符串

数组基本使用

普通数组赋值
  • 普通数组的赋值(注意:普通数组仅能使用整数来作为索引)
    方式一:针对每个索引进行赋值(数组名[索引]=变量值)

    array[0]=pear
    array[1]=apple
    array[2]=orange

    方式二:一次赋多个值(数组名=(多个变量值))

    array3=(tom jack alice [20]=docker)
    echo ${array3[@]}
    tom jack alice docker
    echo ${!array3[@]}
    0 1 2 20
普通数组元素访问
  1. 数组名加索引即可访问数组中的元素

    echo ${array[0]}
    pear
  2. 访问数组中所有的数据

    echo ${array[@]}
    pear apple orange
  3. 获取数组中的索引,在数据遍历的时候有用

    echo ${!array[@]}
    0 1 2
  4. 统计数组元素的个数

    echo ${#array[@]}
    3
关联数组赋值
  • 关联数组的赋值(注意:关联数组能使用字符串的方式作为索引)
  1. 必须先申明这是一个关联数组
    declare -A info

  2. 方式一:关联数组的赋值,数组名[索引]=变量值

    info[index1]=pear
    info[index2]=apple
    info[index3]=orange
  3. 方式二:关联数组的赋值,数组名([索引1]=变量值1 [索引2]=变量值2)
    info2=([index1]=linux [index2]=nginx [index3]=docker [index4]='bash shell')

  4. 查看关联数组

    declare -A
    declare -A info='([index1]="pear" [index2]="apple" [index3]="orange" )'
    declare -A info2='([index4]="bash shell" [index1]="linux" [index2]="nginx" [index3]="docker" )'
关联数组访问
  1. 访问数组中的第二个元素

    echo ${info2[index2]}
    nginx
  2. 访问数组中所有数据

    echo ${info2[@]}
    bash shell linux nginx docker
  3. 访问数组中所有元素的索引

    echo ${!info2[@]}
    index4 index1 index2 index3

普通数组场景

普通数组示例脚本
cat array01.sh
#!/usr/bin/bash

i=0
while read line
do
        hosts[i++]=${line}
done < /etc/hosts

for i in ${!hosts[@]}
do
        echo 索引:$i 索引对应的内容:"${hosts[$i]}"
done

# 执行结果如下
sh array01.sh
索引:0 索引对应的内容:127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
索引:1 索引对应的内容:::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
实现货币兑换系统脚本
  • 根据业务需求,现要求开发一个货币兑换的服务系统,具体要求如下

    • 1.实现人民币兑换美元的功能
    • 2.实现美元兑换人民币的功能
    • 3.实现人民币兑换欧元的功能
  • 货币兑换利率:1美元=7.14人民币、1元=0.12欧元

sh exchange.sh
******欢迎使用货币转换服务系统******
====================================
1.欢迎使用 人民币转换美元 服务
您需要转换的人民币为:100 元
兑换成美元为:14.01$
====================================
2.欢迎使用 美元转换人民币 服务
您需要转换的美元为:100 $
兑换成人民币为:714RMB
====================================
3.欢迎使用 人民币转换欧元 服务
您需要转换的人民币为:100 元
兑换成欧元为:12.00欧

cat exchange.sh
#!/usr/bin/bash

your_money=100
service_menu=(人民币转换美元 美元转换人民币 人民币转换欧元)

echo "******欢迎使用货币转换服务系统******"
for service in ${!service_menu[@]}
do
        if [ $service -eq 0 ];then
                echo "===================================="
                echo "1.欢迎使用 ${service_menu[service]} 服务"
                echo "您需要转换的人民币为:$your_money 元"
                new_money=$(awk -v your_money=$your_money 'BEGIN {printf "%.2f",your_money/7.14}')
                echo "兑换成美元为:${new_money}$"
        fi
        if [ $service -eq 1 ];then
                echo "===================================="
                echo "2.欢迎使用 ${service_menu[service]} 服务"
                echo "您需要转换的美元为:$your_money $"
                new_money=$(awk -v your_money=$your_money 'BEGIN {print your_money*7.14}')
                echo "兑换成人民币为:${new_money}RMB"
        fi
        if [ $service -eq 2 ];then
                echo "===================================="
                echo "3.欢迎使用 ${service_menu[service]} 服务"
                echo "您需要转换的人民币为:$your_money 元"
                new_money=$(awk -v your_money=$your_money 'BEGIN {printf "%.2f",your_money*0.12}')
                echo "兑换成欧元为:${new_money}欧"
        fi
done
获取系统所有端口的脚本
  • 需求:使用shell数组编写脚本,用来获取主机的所有端口,效果如下:
sh discovery_port.sh
{
        "data":[
                {"{#TCP_PORT}":"10050"},
                {"{#TCP_PORT}":"111"},
                {"{#TCP_PORT}":"22"},
                {"{#TCP_PORT}":"3306"},
                {"{#TCP_PORT}":"80"},
                {"{#TCP_PORT}":"9000"}
        ]
}

cat discovery_port.sh
#!/usr/bin/bash

# 数组
array_port=($(netstat -lntp | awk '{print $4}' | awk -F : '{print $NF}' | egrep "^[0-9]+" | sort | uniq))

# 统计数组的长度
array_langth=${#array_port[@]}

# 定义一个变量
index=1

# 遍历数组,组装数据
printf "{\n"
printf "\t\"data\":[\n"

for port in ${array_port[@]}
do
        if [ $index -eq $array_langth ];then
                printf "\t\t{\"{#TCP_PORT}\":\"$port\"}\n"
        else
                printf "\t\t{\"{#TCP_PORT}\":\"$port\"},\n"

        fi
        index=$[ index + 1 ]
done

printf "\t]\n"
printf "}\n"

数组遍历与循环

什么是数组遍历
  • 数组遍历其实就是使用对数组进行批量赋值,然后通过循环方式批量取出数组的值
数组遍历的意义
  • 数组遍历的意义在于,统计某个字段出现的次数,那么遍历的方式有如下两种:
    - 1.通过数组的个数进行遍历(不推荐)

    • 2.通过数组的索引进行遍历(推荐)
  • 如果需要统计一个文件中某个字段出现的次数,怎么办?

    • 要统计谁就将谁作为数组的索引,然后获取索引出现的次数
    • 值得一提的是该方法仅支持关联数组
关联数组统计示例脚本

统计文件中男生、女生出现的次数

  1. 准备对应的文件
cat sex.txt
jack m
alice f
tom m
rose f
robin m
yj m
cindy f

# 第二列作为索引名称,然后让索引名称自增,出现一次+1
# 遍历这个索引,取出对应的值,次数
  1. 编写遍历脚本
cat count_sex.sh
#!/usr/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
  1. 步骤拆分讲解
declare -A sex
sex=([m]=1 [f]=1)
let sex[m]++
let sex[f]++
echo ${!sex[@]}
f m
echo ${sex[@]}
2 2
统计shell类型次数脚本

需求:使用shell数组统计/etc/passwd的不同shell类型的数量

 cat shell_count.sh
#!/usr/bin/bash

declare -A shell

# 对数组进行赋值
while read line
do
        type=$(echo $line | awk -F : '{print $NF}')
        let shell[$type]++
done < /etc/passwd

# 对数组进行遍历
for i in ${!shell[@]}
do
        echo 索引是$i,索引的值是:${shell[$i]}
done
统计nginx ip次数脚本

需求:使用shell数组统计/var/log/nginx/access.log文件,相同ip访问的次数

cat array_nginx_count.sh
#!/usr/bin/bash
declare -A nginx

# 给关联数组的索引进行赋值
while read line
do
        type=$(echo $line | awk '{print $1}')
        let nginx[$type]++
done < /var/log/nginx/access.log

# 遍历数组
for i in ${!nginx[@]}
do
        echo "IP是:$i 出现的次数是 ${nginx[$i]}"
done
最后修改日期: 2024年10月10日

留言

撰写回覆或留言

发布留言必须填写的电子邮件地址不会公开。