八、函数和数组

8.1 函数

函数几乎是学习所有的程序设计语言时都必须过的一关。对于学习过其他的程序语言的用户来说,函数可能并不陌生。但是Shell中的函数与其他的程序设计语言的函数有许多不同之处。

8.1.1什么是函数

通俗地讲,所谓函数就是将一组功能相对独立的代码集中起来,形成一个代码块,这个代码可以完成某个具体的功能。从上面的定义可以看出,Shell中的函数的概念与其他语言的函数的概念并没有太大的区别。从本质上讲,函数是一个函数名到某个代码块的映射。也就是说,用户在定义了函数之后,就可以通过函数名来调用其所对应的一组代码。使用shell函数优势

1、把相同的程序段定义为函数,可以减少整个程序段代码量,提升开发效率。

2、增加程序段可读性、易读性,提升管理效率。

3、可以实现程序功能模块化,使得程序具备通用性(可移植性)。

8.1.2函数语法

function 函数名() {指令return
}简化写法1:
function 函数名 {指令return
}简化写法2: 
函数名 () {指令return
}

8.1.3函数的调用

在Shell中,函数调用的基本语法如下:

function_name param param2 ...

在上面的语法中,function_name表示函数名称,其后面跟的param1、param2...表示函数的参数。Shell的函数参数的语法比较特殊。实际上,Shell将脚本参数和函数参数做了统一地处理。也就是说,Shell采用了相同的方法来处理脚本的参数和函数参数。

(1)调用函数:直接执行函数名即可。

函数名

(2)带参数的函数执行方法:

函数名 参数

与Shell脚本一样,用户可以在Shell函数中使用位置变量来获取参数值。例如,$0表示脚本名称,$#来获取函数的参数个数,$1表示第1个参数,$2表示第2个参数等,以此类推。另外,用户还可以通过系统变量$@和$*获取所有参数的值。

[root@kittod ~] # cat func01.sh
#!/bin/bash
func ( )
{echo "the function has $# parameters"echo "all parameters are $*"echo "all parameters are $@"echo "the script name is $0"echo "the first parameter is $1"
}func hello world[root@kittod~]# bash func01.sh
the function has 2 parameters
all parameters are hello world
all parameters are hello world
the script name is func01.sh
the first parameter is hello

8.1.4函数的返回值

首先,用户可以使用return语句来返回某个数值,这与绝大部分的程序设计语言是相同的。但是,在Shell中, return语句只能返回某个0~255之间的整数值。

在函数中,用户将需要返回的数据写入到标准输出(stdout),通常这个操作是使用echo语句来完成的。然后在调用程序中将函数的执行结果赋给一个变量。这种做法实际上就是命令替换的一个变种。

例:

[ root@kittod ~] # cat length.sh
#!/bin/bash
length()
{str=$1result=0if [ "$1" != "" ];thenresult=${#str}  	#	!#为长度fiecho "$result"
}
len=$(length "abcd12")  #$()变量替换
echo "the string's length is $len"
[root@kittod ~]# bash length.sh
the string's length is 6

8.1.5 函数案例

示例1:写一个脚本,判定192.168.33.120-192.168.33.130之间的主机哪些在线。

要求:

1、使用函数来实现一台主机的判定过程;

2、在主程序中来调用此函数判定指定范围内的所有主机的在线情况。直接使用函数实现

方法一:直接使用函数实现(无参数,无返回值)

[root@kittod ~]# cat online01.sh
#!/bin/bashonline()
{for i in {120..130};doif ping -c 1 192.168.33.$i &>/dev/nullthenecho "192.168.33.$i is up"elseecho "192.168.33.$i is unknown"fidone
}online

方法二:使用函数传参(有参数,无返回值)

[root@kittod ~]# cat online02.sh
#!/bin/bashonline()
{if ping -c 1 $1 &>/dev/nullthenecho "$1 is up"elseecho "$1 is unknown"fi
}for i in {120..130}
doonline 192.168.33.$i
done

方法三:使用函数返回值判断(有参数,有返回值)

[root@kittod ~]# cat online03.sh
#!/bin/bashonline()
{if ping -c 1 $1 &>/dev/nullthenreturn 0elsereturn 1fi
}for i in {120..130}
doonline 192.168.33.$iif [ $? -eq 0 ];thenecho "192.168.33.$i is up"elseecho "192.168.33.$i is unknown"fi
done

示例2:写一个脚本,使用函数完成

1、函数能够接受一个参数,参数为用户名;

判断一个用户是否存在

如果存在,就返回此用户的shell和UID;并返回正常状态值;

如果不存在,就说此用户不存在;并返回错误状态值;

2、在主程序中调用函数;

[root@kittod ~]# cat userms.sh
#!/bin/bash
user()
{if id $1 &>/dev/nullthenecho "`grep ^$1 /etc/passwd | cut -d: -f3,7`"return 0elseecho "$1 does not exist"return 1fi
}read -p "please input username:" username
until [ "$username" = "quit" -o "$username" = "exit" -o "$username" = "q" ]
douser $usernameif [ $? == 0 ];thenread -p "please input again:" usernameelseread -p "no $username,Please input again:" usernamefi
done[root@kittod ~]# bash userms.sh
please input username:redhat
1000:/bin/bash
please input again:root
0:/bin/bash
please input again:dakuang
dakuang does not exist
no dakuang,Please input again:hehe
hehe does not exist
no hehe,Please input again:quit

8.1.6 函数库文件

为了方便地重用这些功能,可以创建一些可重用的函数。这些函数可以单独地放在函数库文件中。

·函数库文件定义:

创建一个函数库文件的过程非常类似于编写一个Shell脚本。脚本与库文件之间的唯一区别在于函数库文件通常只包括函数,而脚本中则可以既包括函数和变量的定义,又包括可执行的代码。此处所说的可执行代码,是指位于函数外部的代码,当脚本被载入后,这些代码会立即被执行,毋需另外调用。

·函数库文件的调用

当库文件定义好之后,用户就可以在程序中载入库文件,并且调用其中的函数。在Shell中,载入库文件的命令为.,即一个圆点,其语法如下:

. filename

其中,参数filename表示库文件的名称,必须是一个合法的文件名。库文件可以使用相对路径,也可以使用绝对路径。另外,圆点命令和库文件名之间有一个空格。

8.1.7 递归函数

Linux的Shell也支持函数的递归调用。也就是说,函数可以直接或者间接地调用自身。在函数的递归调用中,函数既是调用者,又是被调用者。

递归函数的调用过程就是反复地调用其自身,每调用一次就进入新的一层。

示例:根据用户输入的数值计算该数的阶乘

[root@kittod ~]# cat fact.sh
#!/bin/bashfact()
{
local n="$1"   #local   定义局部变量
if [ "$n" -eq 0 ]
thenresult=1
elselet "m=n-1"fact "$m"let "result=$n * $?"
fireturn $result
}fact "$1"
echo "Factorial of $1 is $?"[root@kittod ~]# bash fact.sh 0
Factorial of 0 is 1
[root@kittod ~]# bash fact.sh 5
Factorial of 5 is 120

注意:默认情况下,除了与函数参数关联的特殊变量之外,其他所有的变量都有全局的有效范围。另外,在函数内部,如果没有使用local关键字进行修饰,那么函数中的变量也是全局变量。

例1:函数的变量是全局变量

[root@kittod ~]# cat global.sh
#!/bin/bash
var="hello world"
func()
{var="orange"echo $varvar2="hello"
}
echo "$var"
func
echo "$var"
echo "$var2"
[root@kittod ~]# bash global.sh
hello world
orange
orange
hello

例2:函数的变量使用local指定为局部变量

[root@kittod ~]# cat global02.sh
#!/bin/bash
var="hello world"
func()
{local var="orange"echo $varlocal var2="hello"
}
echo "$var"
func
echo "$var"
echo "$var2"[root@kittod ~]# bash global02.sh
hello world
orange
hello world

8.2 数组

所谓数组,是指将具有相同类型的若干变量按照一定的顺序组织起来的一种数据类型。Shell语言对于数组的支持非常强大。在Shell中,用户可以通过多种方式来创建一个数组。

8.2.1 定义数组

定义数组

方法一:用小括号将变量值括起来赋值给数组变量,每个变量之间要用空格进行分隔

array=(value1 value2 value3 ... )

方法二:用小括号将变量值括起来,同时采用键值对的形式赋值。当通过键值对定义数组时,用户所提供的键值对中的元素索引不一定是连续的,可以任意指定要赋值的元素的索引。之所以可以这样操作,是因为用户已经显式指定了索引,Shell就可以知道值和索引的对应关系。

array=([0]=one [1]=two [2]=three ... [n]=valuen)

方法三:分别定义数组变量的值

array[0]=a;array[1]=b;array[2]=c

方法四:动态的定义变量,并使用命令的输出结果作为数组的内容。

array=(命令)

方法五:通过declare语句定义数组

declare -a array

定义关联数组:关联数组使用字符串作为下标,而不是整数,这样可以做到见名知意。 不同于普通数组,关联数组必须使用带有-A选项的 declare 命令创建。

方法一:一次赋一个值
[root@kittod ~]# declare -A array
[root@kittod ~]# array[shuju1]=apple
[root@kittod ~]# array[shuju2]=banana
[root@kittod ~]# echo ${array[*]}
banana apple方法二:一次赋多个值
[root@kittod ~]# declare -A a
[root@kittod ~]# a=([index1]=tom [index2]=jack [index3]=alice)
[root@kittod ~]# echo ${a[@]}
tom jack alice

8.2.2 数组操作

获取所有元素:
[root@kittod ~]# echo ${array[*]} # *和@ 都是代表所有元素
banana apple获取元素下标:
[root@kittod ~]# echo ${!array[@]}  #${!}取下标
shuju2 shuju1
[root@kittod ~]# echo ${!array[*]}  #${!}取下标
shuju2 shuju1获取数组长度:
[root@kittod ~]# echo ${#array[*]}  #${#}取数组的长度
2
[root@kittod ~]# echo ${#array[@]} 
2获取元素:
[root@kittod ~]# echo ${array[shuju1]}
apple
[root@kittod ~]# echo ${array[shuju2]}
banana添加元素:
[root@kittod ~]# array[3]=d
[root@kittod ~]# echo ${array[3]}
d删除一个元素:
[root@kittod ~]# unset array[shuju1]
[root@kittod ~]# echo ${array[shuju1]}删除数组:
[root@kittod ~]# unset array
[root@kittod ~]# mkdir /array
[root@kittod ~]# touch /array/{1..5}.txt
[root@kittod ~]# ll /array/
total 0
-rw-r--r--. 1 root root 0 May 18 18:03 1.txt
-rw-r--r--. 1 root root 0 May 18 18:03 2.txt
-rw-r--r--. 1 root root 0 May 18 18:03 3.txt
-rw-r--r--. 1 root root 0 May 18 18:03 4.txt
-rw-r--r--. 1 root root 0 May 18 18:03 5.txt
[root@kittod ~]# array2=($(ls /array/))
[root@kittod ~]# echo ${array2[@]}
1.txt 2.txt 3.txt 4.txt 5.txt
[root@kittod ~]# echo ${array2[*]}
1.txt 2.txt 3.txt 4.txt 5.txt
[root@kittod ~]# echo ${array2[1]}
2.txt
[root@kittod ~]# echo ${array2[0]}
1.txt
[root@kittod ~]# echo ${array2[4]}
5.txt

遍历数组:

方法 1:
#!/bin/bash
IP=(192.168.1.1 192.168.1.2 192.168.1.3)
for ((i=0;i<${#IP[*]};i++)); do
echo ${IP[$i]}
done
# bash test.sh
192.168.1.1
192.168.1.2
192.168.1.3方法 2:
#!/bin/bash
IP=(192.168.1.1 192.168.1.2 192.168.1.3)
for IP in ${IP[*]}; do
echo $IP
done

8.2.3 数组案例

1、从“标准输入”读入n次字符串,每次输入的字符串保存在数组array里

[root@kittod ~]# cat str.sh
#!/bin/bashi=0
n=5
while [ "$i" -lt $n ];doecho "Please input strings... `expr $i + 1`"read array[$i]b=${array[$i]}echo "$b"i=`expr $i + 1`
done[root@kittod ~]# bash str.sh
Please input strings... 1
s
s
Please input strings... 2
e
e
Please input strings... 3
eeeeeeeeeeeeeeee
eeeeeeeeeeeeeeee
Please input strings... 4
ggggggggggggggggggggggwewe
ggggggggggggggggggggggwewe
Please input strings... 5
ddddd
ddddd

2、将字符串里的字母逐个放入数组,并输出到“标准输出”

[root@kittod ~]# cat letter.sh
#!/bin/bashchars='afjlksjdfljsldjflsdfj'
for ((i=0;i<${#chars};i++));doarray[$i]=${chars:$i:1}echo ${array[$i]}
done说明:${chars:$i:1},表示从chars字符串的 $i 位置开始,获取 1 个字符

3、把1-3这3个数字存到数组里,分别乘以8然后依次输出。

[root@kittod ~]# vim number.sh
#!/bin/bash
array=(`seq 3`) #seq 3   就是123
for ((i=0;i<${#array[@]};i++))
doecho $[${array[$i]}*8]
done
[root@kittod ~]# bash number.sh
8
16
24

4、打印下面这句话中字母数不大于6的单词:

cat is favorite to eat fish

[root@kittod ~]# vim word.sh
#!/bin/bash
array=(cat is favorite to eat fish)
for i in ${array[*]}
do
if [ ${#i} -lt 6 ]thenecho $ifi
done
[root@kittod ~]# bash word.sh
cat
is
to
eat
fish

练习:

1、编写函数,实现打印绿色OK和红色FAILED判断是否有参数,存在为Ok,不存在为FAILED
2、编写函数,实现判断是否无位置参数,如无参数,提示错误
3、编写函数实现两个数字做为参数,返回最大值
4、编写函数,实现两个整数位参数,计算加减乘除。
5、将/etc/shadow文件的每一行作为元数赋值给数组
6、使用关联数组统计文件/etc/passwd中用户使用的不同类型shell的数量
7、使用关联数组按扩展名统计指定目录中文件的数量

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/15729.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

记忆力和人才测评,如何提升记忆力?

什么是记忆力&#xff1f; 如何通俗意义上的记忆力&#xff1f;我们可以把人的经历、经验理解成为一部纪录片&#xff0c;那么已经过去发生的事情&#xff0c;就是影片之前的情节&#xff0c;对于这些信息&#xff0c;在脑海里&#xff0c;人们会将其进行处理和组合&#xff…

SAP-CO成本控制概念之标准成本

“ 本篇介绍&#xff1a;标准成本的会计概念&#xff0c;标准成本的制定标准&#xff1b;通过结合会计标准成本的概念与SAP CO标准成本估算功能&#xff0c;更具象化的了解SAP如何实现标准成本管理&#xff0c;为后续学习SAP实际成本核算打下基础。” 01 — 背景需求 SAP实施…

2024年春招高薪职业报告:大模型算法研究员领跑

近日&#xff0c;脉脉高聘发布的研究报告《2024春招高薪职业和人才洞察》&#xff08;以下简称《洞察》&#xff09;显示&#xff0c;2024年一季度&#xff0c;大模型算法研究员新发岗位以平均月薪6.4万元领跑高薪岗位榜。受人才培养周期和技术门槛影响&#xff0c;人工智能行业…

机器学习大模型驱动:未来的趋势与应用

文章目录 &#x1f4d1;前言一、什么是机器学习大模型&#xff1f;1.1 大模型的特点1.2 大模型的技术基础 二、大模型的技术实现2.1 Transformer 架构2.2 预训练和微调2.3 模型并行和数据并行 三、大模型的应用场景3.1 自然语言处理&#xff08;NLP&#xff09;3.2 计算机视觉&…

vue3 使用css实现一个弧形选中角标样式

文章目录 1. 实现效果2. 实现demo 在前端开发中&#xff0c;ui同学经常会设计这样的样式&#xff0c;用于区分选中的状态 下面抽空简单些了一下&#xff0c;记录下&#xff0c;后面直接复制用 1. 实现效果 实现一个菜单切换&#xff0c;右下角有个角标的样式 2. 实现demo 主要…

Java进阶学习笔记20——枚举

认识枚举&#xff1a; 枚举是一种特殊的类。 枚举类的格式&#xff1a; 说明&#xff1a; 第一行是罗列枚举的对象名称。只能写合法的标识符&#xff08;名称&#xff09;&#xff0c;多个名称用逗号隔开。 这些名称本质上都是常量&#xff0c;每个变量都会记住枚举类的一个…

Optica数据库 (原OSA美国光学学会电子期刊)文献去哪里查找下载

Optica&#xff08;OSA&#xff09;数据库涵盖了光学和光子学理论研究和实际应用的各个领域&#xff0c;包括&#xff1a;光学设备、光学成像、光纤通信、分析方法、光通信、光纤、半导体激光、光传输、光学系统、计量学、带宽、量子电子学。 该库包括18种学会期刊&#xff08…

MVCC 原理分析、MySQL是如何解决幻读的

文章目录 一、前言回顾1.1 事务四大特性ACID1.2 并发事务问题1.3 事务隔离级别 二、MVCC2.1 为什么使用MVCC2.2 基本概念——当前读、快照读、MVCC2.2.1 当前读2.2.2 快照读2.2.3 MVCC 2.3 隐藏字段—— TRX_ID、ROLL_PTR2.4 undo log2.4.1 介绍2.4.2 版本链 2.5 Read View读视…

python写接口性能测试

import time import requestsdef measure_response_time(api_url):try:start_time time.time()response requests.get(api_url, timeout10) # 设置超时时间为10秒end_time time.time()response_time end_time - start_timeprint(f"接口 {api_url} 的响应时间为&#…

读书笔记-Java并发编程的艺术-第1章 并发编程的挑战

文章目录 1.1 上下文切换1.1.1 多线程一定快吗1.1.2 如何减少上下文切换 1.2 死锁1.3 资源限制的挑战 1.1 上下文切换 即时是单核处理器也支持多线程执行代码&#xff0c;CPU通过给每个线程分配CPU时间片来实现这个机制。时间片是CPU分配给多个线程的时间&#xff0c;因为时间…

C++拓展之scanf和printf

scanf和printf&#xff0c;这东西&#xff0c;说难也不难&#xff0c;可一旦深入学&#xff0c;学两天都可能学不完。 为了输入输出&#xff0c;我们要把这些占位符学一学。 我们来看看AI是怎么回答的。 Q&#xff1a;C格式化占位符有哪些&#xff1f; A&#xff1a;C中常用的…

【手把手带你搓组件库】从零开始实现Element Plus

从零开始实现Element Plus 前言亮点项目搭建1、创建项目初始化monorepo创建 .gitignore目录结构安装基础依赖配置文件创建各个分包入口utilscomponentscoreplaytheme 2、创建VitePress文档3、部署到Github Actions生成 GH_TOKENGitHub Page 演示 4、总结 前言 在本文中&#xf…

面向可复用性和可维护性的设计模式 课程学习总结

什么是设计模式 设计模式&#xff1a;在软件设计中给定上下文中常见问题的通用的、可重用的解决方案。 设计模式分类 1. 创建型模式——Creational patterns 关注对象创建的过程 1.1 工厂方法模式 定义用于创建对象的接口&#xff0c;但让子类决定要实例化哪个类。工厂方…

4.Redis之Redis的通用命令

0.Redis 实战操作 通过 redis-cli 客户端和 redis 服务器交互 涉及到很多的 redis 的命令 【redis 的命令非常非常多!!! 1.掌握常用命令(多操作多练习) 2.学会使用 redis 的文档-> 阅读文档, 是程序猿的基操!! redis 的命令非常非常多!!! 1.掌握常用命令(多操作多练习…

部署CNI网络组件+k8s多master集群部署+负载均衡

一、环境部署 主机服务 192.168.91.5 K8S集群master01192.168.91.8 K8S集群master02192.168.91.6K8S集群node01192.168.91.7K8S集群node02192.168.91.9 负载均衡nginxkeepalive01&#xff08;master&#xff09;192.168.91.10 负载均衡nginxkeepalive02&#xff08;backup&am…

编程实战:自己编写HTTP服务器(系列3:处理框架)

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 系列入口&#xff1a;编程实战…

TypeScript学习日志-第三十二天(infer关键字)

infer关键字 一、作用与使用 infer 的作用就是推导泛型参数&#xff0c;infer 声明只能出现在 extends 子语句中&#xff0c;使用如下&#xff1a; 可以看出 已经推导出类型是 User 了 二、协变 infer 的 协变会返回联合类型&#xff0c;如图&#xff1a; 三、逆变 infer…

pikachu靶场中的CSRF、SSRF通关

目录 1、CSRF介绍 2、CSRF&#xff08;get&#xff09; 3、CSRF&#xff08;post&#xff09; 4、CSRF Token 5、SSRF介绍 6、SSRF&#xff08;curl&#xff09; 7、SSRF&#xff08;file_get-content&#xff09; 8、CSRF与SSRF的区别 最近在学习CSRF、SSRF漏洞&#…

Boyer-Moore投票算法

摩尔投票法&#xff0c;又称为博耶-摩尔多数投票算法&#xff0c;是一种用于在一组数据中寻找多数元素(出现次数超过一半的元素)的算法。该算法的效率非常高&#xff0c;时间复杂度为O(n)&#xff0c;空间复杂度为O(1)&#xff0c;适合处理大数据量的情况。 步骤 首先定义两个…

飞机大战游戏实现揭秘

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、游戏概览与核心玩法 二、游戏模块详解 1. 游戏主循环模块 2. 创建初始化模块 三、关…