Shell 函数 & 数组

Shell 函数

函数介绍

# 什么是函数?
    具备某一功能的工具 => 函数
    事先准备工具的过程 => 函数的定义
    遇到应用场景拿来就用 => 函数的调用
    
# 为何要用函数?
	没有引入函数前,遇到重复使用某一个功能的地方,只能复制黏贴实现该功能的代码,这会导致
	1、代码冗余 => 程序组织结构不清晰,可读性差
        2、如果该功能的代码需要修改,那么需要找到所有黏贴这段代码的地方进行修改 => 可扩展性差

# 如何用函数?
	函数的使用应该遵循一个原则:先定义、再调用

函数的基本使用

定义函数

# 格式1: 推荐
function 函数的名字() {
    命令1
    命令2
    命令3
    ...
}

# 格式2
function 函数的名字 {
    命令1
    命令2
    命令3
    ...
}

# 格式3
函数的名字() {
    命令1
    命令2
    命令3
    ...
}

调用函数

# 直接函数的名字
[root@zzzwqh sample]# fun.sh
#!/bin/bash
function onepieace() {
    echo "For ONEPIECE"
}
# 函数调用
onepieace

[root@zzzwqh sample]# ./fun.sh
For ONEPIECE

函数的参数传递

函数的位置参数

[root@zzzwqh sample]# cat add.sh
#!/bin/bash

function add() {
    # [ $# -ne 2 ] && echo "必须为函数传入两个参数" && exit
    [ $# -ne 2 ] && echo "必须为函数传入两个参数" && return
    res=$[ $1 + $2 ]
	echo "$1+$2=$res"
}

add 10 11 
     
echo "exit 结束进程,return 结束函数代码流程"
[root@zzzwqh sample]# ./add.sh 
10+11=21
exit 结束进程,return 结束函数代码流程

进程的全局变量

[root@zzzwqh sample]# cat add.sh
#!/bin/bash
a=$1
b=$2
function add() {
    res=$[ $a + $b ]
	echo "$a+$b=$res"
}

add
[root@zzzwqh sample]# ./add.sh 10 11
10+11=21

函数的返回值

在 Shell 语言中 Return 返回的是函数运行的状态,而且只能返回值 Int 型(0-255),

Return 是函数结束的标志,函数内可以有多个 Return,但只要执行一次,整个函数就立即结束,并且将 Return 后的当做函数的运行状态返回

#!/bin/bash

function test() {
    echo "Hello"
    return 0
    echo "World"
    return 255
    echo "I'm Back"
    return 256
}

test
echo $?

如果函数体代码没有 Return ,那么函数的运行状态默认就是函数体代码最后一条命令的运行状态

变量的作用域

  • 局部作用域 => 函数内用 Local 关键字声明的变量 => 只能在函数内访问
#!/bin/bash

function f1() {
    local x=111  # 局部变量需要用 local 声明  
	echo $x 	 # 在函数内找
}
f1
echo $x 		 # 在函数外找
  • 全局作用域 => 在当前进程内声明的变量 => 可以在当前进程的任意位置访问到
[root@zzzwqh sample]# cat test.sh
#!/bin/bash
y=222  # 全局变量
function f2() {
    echo $y
}
f2
echo $y

# PS:只要没有被 local 声明的变量,都是全局变量,都是在整个进程有效,下面方式的定义的变量仍然可以输出
[root@zzzwqh sample]# cat test.sh
#!/bin/bash
function f2() {
    z=333		# 全局变量
    echo $z
}
f2
echo $z
  • 环境变量
export 声明的变量称之为环境变量,环境变量的范围:父进程定义的环境变量,子子孙孙进程都可以看到

# 注意:
​ 1、传子不传爹
​ 2、没有父子关系 export 无效

所以将 export 语句加入 /etc/profile 等文件中,每开启一个终端 Bash 之前,都会运行 /etc/profile 等文件,

Shell 数组

数组介绍

# 1、数组
一组数据的集合,与整型、浮点型、字符串型不同的是一个数组可以同时存放多个值

# 2、为何要用数组
把相关的变量归置到一起,程序的组织结构更清晰

# 3、如何用数组

数组的基本使用

定义数组

# 方式一
array=(1.3 111 "aa")

# 方式二
array=([0]=1.3 [1]=111 [2]="aaa")

ps: 可以换顺序,也可空着来
array=([2]="aaa" [0]=1111111)

# 方式三
[root@zzzwqh ~]# array[0]=1.3
[root@zzzwqh ~]# array[2]="aaa"

# 方式四:
[root@zzzwqh ~]# array=(`ls .`)

[root@zzzwqh ~]# echo ${array[0]}
anaconda-ks.cfg
[root@zzzwqh ~]# echo ${array[1]}
check_httpd.sh
[root@zzzwqh ~]# echo ${array[2]}

操作数组

# 重新定义数组
unset array
array=(1.3 111 "aa")
# 1、查看数组元素
echo ${array[0]}
echo ${array[-1]}

echo ${array[*]}  # 查看数组内所有元素
echo ${array[@]}  # 查看数组内所有元素

echo ${#array[*]}  # 查看数组内元素的个数
4

[root@zzzwqh ~]# declare -a  # 查看声明过的数组
# 2、修改和添加
array[0]=3.6
array[5]=3333
    
# 3、删除
删除整个数组
unset array
    
删除某一个
[root@zzzwqh ~]# array=(1.3 111 "aa")
[root@zzzwqh ~]# echo ${array[*]}
1.3 111 aa
[root@zzzwqh ~]# 
[root@zzzwqh ~]# unset array[1]
[root@zzzwqh ~]# echo ${array[*]}
1.3 aa
[root@zzzwqh ~]# 

# 4、截取(了解)
指定索引截取
[root@zzzwqh ~]# array=(zzzwqh 18 male IT 1.80 11 22 33)
[root@zzzwqh ~]# echo ${array[*]:3:2}
IT 1.80
[root@zzzwqh ~]# 

指定元素删除(不改变原数组)
array=(one two three four five fire)
echo ${array[*]#one}
echo ${array[*]#five} 
echo ${array[*]#f*e} 
       
# 5、替换(了解)
[root@zzzwqh ~]# array=(one two three four five fire)
[root@zzzwqh ~]# echo ${array[*]/f*e/111}
one two three four 111 111

关联数组

上面介绍的索引对应元素的数组称之为普通数组
关联数组指的是可以指定 Key 对应 Value

[root@zzzwqh ~]# declare -A array=(["name"]="zzzwqh" ["age"]=18 ["gender"]="male")
[root@zzzwqh ~]# echo ${array["age"]}		# 获取某个键的值
18
[root@zzzwqh ~]# echo ${array[*]}			# 获取关联数组所有的值
male zzzwqh 18
[root@zzzwqh ~]# echo ${array[@]}			# 同上
male zzzwqh 18
[root@zzzwqh ~]# echo ${#array[@]}			# 获取关联数组键值对个数
3
[root@zzzwqh ~]# echo ${#array["name"]}			# 获取关联数组值的长度 
6
[root@zzzwqh ~]# echo ${!information[@]}	        # 获取关联数组所有的键
gender name age

# declare -A 查看定义的全部关联数组

数组的遍历

遍历普通数组的方式 1:取值

array=(one two three four five fire)
# * 号也可以用 @
for i in ${array[*]}
do
    echo $i
done

遍历普通数组的方式 2:取索引,进而取值

array=(one two three four five fire)

for i in ${!array[*]}
do
    echo $i ${array[$i]}  # 获取索引及其对应的元素
done

遍历关联数组的方式 1: 取值

declare -A array=(["name"]="zzzwqh" ["age"]=18 ["gender"]="male")

for x in ${array[*]}
do
   echo $x
done

遍历关联数组的方式 2: 取 key,进而取 value

declare -A array=(["name"]="zzzwqh" ["age"]=18 ["gender"]="male")

for k in ${!array[*]}
do
   echo $k ${array[$k]}
done

数组相关练习

基于关联数组统计 /etc/passwd 文件中不同种类 Shell 的个数

[root@zzzwqh sample]# cat 11.sh 
#!/bin/bash

declare -A shell_count

while read line
do
    s=`echo $line|awk -F: '{print $7}'`
    let shell_count[$s]++
done < /etc/passwd

for k in  ${!shell_count[@]}
do
   echo $k ${shell_count[$k]}
done
[root@zzzwqh sample]# ./11.sh 
/sbin/nologin 21
/bin/sync 1
/bin/bash 2
/sbin/shutdown 1
/sbin/halt 1
[root@zzzwqh sample]# 
记录成长过程
原文地址:https://www.cnblogs.com/zzzwqh/p/13589975.html