Shell基础之函数和数组

目录

函数

什么是函数

函数的语法

函数的调用

函数的返回值

函数的案例

函数变量的作用域

递归函数

函数库文件

数组

定义数组语法

数组操作

获取所有元素

获取元素下标

获取数组长度

获取数组元素

数组添加元素

删除数组元素

删除数组

遍历数组元素

数组案例


函数

什么是函数

        所谓函数,与其他语言中的函数没有太大的本质区别。它们是完成特定功能的代码块,这个代码块是可以重复使用的,并是一组命令或者语句组成

        在Shell中,函数本质上就是将函数名称与要实现的特殊功能的代码进行引用的一种方式

在Shell中函数具有以下的优势

把相同的程序代码定义函数,这样就可以重复利用,从而提长开放的效率
增加了程序代码段的可读性和提升管理效率
可以实现程序功能的模块化。使得程序具备通用性

函数的语法

在Shell中,函数具有以下的语法结构:

#完整结构
function 函数名称() {指令或语句return [返回值]
}#简化结构
function 函数名称 {指令或语句return [返回值]
}#进一步简化的结构
函数名称() {指令或语句return [返回值]
}

函数的调用

        在Shell中,调用函数之前,该函数必须存在

调用函数的基本语法如下:

函数名称 [参数1 参数2 参数3 ......]

        对于函数的调用,可以有以下方法:

$#获取参数的个数
$1、$2、$3......获取是第几个参数
$@ 或者 $*获取所有的参数列表

示例:

        定义一个名称叫 fun 的函数,并且调用 fun 函数

[root@openEuler ~]# cat fun1.sh
#!/bin/bash# 定义一个名称叫 fun 的函数
fun() {echo "the function has $# parameters"echo "all parameters $@"echo "first parameter $1"echo "second parameter $2"
}# 调用定义好的 fun 函数
fun hello world[root@openEuler ~]# bash fun1.sh 
the function has 2 parameters
all parameters hello world
first parameter hello
second parameter world
[root@openEuler ~]# 

注意:

        在Shell中,函数是先定义再使用,如果是先使用再定义,就会报错

报错示例:

[root@openEuler ~]# cat fun1.sh
#!/bin/bash#先调用 fun 函数
fun hello world# 再定义 fun 函数
fun() {echo "the function has $# parameters"echo "all parameters $@"echo "first parameter $1"echo "second parameter $2"
}[root@openEuler ~]# bash fun1.sh 
fun1.sh: line 3: fun: command not found

        如果函数只声明了,但是没有调用这个函数,那么该函数不会执行。但是我们可以使用 . 或者 source 来先执行这个脚本,让函数放到当前的 Shell 环境中,此时我们在 Shell 环境中就可以执行这个函数

示例:

[root@openEuler ~]# cat fun1.sh
#!/bin/bash#只声明 fun 函数,但是没调用函数
fun() {echo "the function has $# parameters"echo "all parameters $@"echo "first parameter $1"echo "second parameter $2"
}#将脚本中的函数放到当前shell 环境中
[root@openEuler ~]# source ./fun1.sh [root@openEuler ~]# fun 1 2
the function has 2 parameters
all parameters 1 2
first parameter 1
second parameter 2

函数的返回值

        在 Shell 中,函数也是可以有返回值的,但是它和其他语言中的函数返回值不太相同

在函数中如果使用 return 语句来退出函数,并返回函数的值时,那么在函数外就需要使用 echo $? 来获取返回的值
在函数中如果使用的是 echo 输出,那么在函数外边就可以使用 变量=$(函数名称) 来获取返回的值

注意:

        在 Shell 中使用 return 返回的只能是整数值,而且范围不能超过0~255,如果超过了则需要与256取模

示例1:

        计算两个参数的和

[root@openEuler ~]# cat fun2.sh 
#!/bin/bash
sum1() {sum=$[$1 + $2]echo $sum
}
read -p "Please enter first number: " first
read -p "Please enter second number: " secondsum1 first second
#或者
res=$(sum1 first second)echo $res[root@openEuler ~]# bash fun2.sh 
Please enter first number: 6     
Please enter second number: 4
10

示例2:

        获取字符串的长度

[root@openEuler ~]# cat fun3.sh 
#!/bin/bash
length() {str=$1len=0if [ "$1" != "" ]; thenlen=${#str}fi      return $len
}       
length "abc123"
echo "the string's length is $?"[root@openEuler ~]# bash fun3.sh 
the string's length is 6

函数的案例

示例1:

        将一个点分十进制格式的IP地址转换成点分二进制格式

比如:255.255.255.255 ——> 11111111.11111111.11111111.11111111

[root@openEuler ~]# cat fun4.sh 
#!/bin/bashdecimal_to_bin() {NUM=$1for i in {1..8}doSUM=$[NUM % 2]$SUMlet NUM/=2#((NUM=NUM/2))doneecho $SUM
}split_ip() {IP=$1for i in {1..4}donum=${IP%%.*}    # IP=192.168.72.150     -> num=192#echo "num=$num"IP=${IP#*.} # IP=168.72.150    delete 192#echo "ip=$IP"BIN=$(decimal_to_bin num)#decimal_to_bin $numecho -n $BINdone
}read -p "Please enter a valid IP address: " INIPres=$(split_ip $INIP)
echo ${res%.*}[root@openEuler ~]# bash fun4.sh 
Please enter a valid IP address: 192.168.72.112
11000000.10101000.01001000.01110000

示例2:

        编写一个脚本,实现判断给定的 IP 地址范围 [192.168.72.130~192.168.72.140] 是否在线

[root@openEuler ~]# cat fun5.sh
#!/bin/bashonline() {for i in {148..152}do      if ping -c1 192.168.72.$i &>/dev/nullthen    echo "192.168.72.$i is up"else    echo "192.168.72.$i is unknow"fi      done    
}       online[root@openEuler ~]# bash fun5.sh
192.168.72.148 is unknow
192.168.72.149 is unknow
192.168.72.150 is up
192.168.72.151 is up
192.168.72.152 is unknow

函数变量的作用域

示例1:

        函数的变量是全局变量

[root@openEuler ~]# cat fun6.sh 
#!/bin/bashstr="hello shell"
func() {str="openlab"echo $strstr2="hello"
}
echo "$str"
func
echo "$str"
echo "$str2"[root@openEuler ~]# bash fun6.sh 
hello shell
openlab
openlab
hello

注意:

        使用 $() 这种方式来执行命令时,变量值还是需要使用 $ 变量名的方式来获取,当使用 $(())来做算术运算时,可以省略 $ 而直接使用变量名

示例:

#!/bin/basha=1
b=2
c=$[ $a + $b ] #`$a+$b`echo `expr $a + $b`echo $(expr $a + $b)echo $cd=$((a+b))
echo $d

示例2:

        函数的变量如果希望是局部的,那么我们需要显式的使用 local 来声明

[root@openEuler ~]# cat fun7.sh 
#!/bin/bashs="ni hao"
func() {local s="ni ye hao"echo $slocal s1="da jia wang shang hao"
}
echo "$s"
func
echo "$s"
echo "${s1}"
[root@openEuler ~]# bash fun7.sh 
ni hao
ni ye hao
ni hao[root@openEuler ~]# 

注意:

        当使用 local 来声明变量时,它就是一个局部变量,离开函数后,这个变量就消失了

递归函数

示例1:

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

[root@openEuler ~]# cat recursion.sh 
#!/bin/bashrecursion() {if [ $1 -eq 1 ] ; thenresult=1elif [ $1 -gt 1 ] ; thenlocal n=$[ $1 - 1 ]recursion $nlet "result=$1 * $?"elseecho "The number is invalid"fireturn $result
}recursion $1
echo $?[root@openEuler ~]# bash recursion.sh 5
120

示例2:

        使用函数递归 /var/log 目录,如果是文件直接输入文件名,如果是目录则输出目录名称并且输出目录下所有子目录和文件名

[root@openEuler ~]# cat fact.sh 
#!/bin/bashlist_file() {for f in $(ls $1)doif [ -d "$1/$f" ]; then #/var/log/anacondaecho "$2 directory $f"list_file "$1/$f" "├── $2"elseecho "$2 file $f"fidone
}
list_file $1 "├── "[root@openEuler ~]# bash fact.sh /var/log
├──  directory anaconda
├── ├──  file anaconda.log
├── ├──  file dbus.log
├── ├──  file dnf.librepo.log
├── ├──  file hawkey.log
├── ├──  file journal.log
├── ├──  file lorax-packages.log
├── ├──  file lvm.log
├── ├──  file packaging.log
├── ├──  file program.log
├── ├──  file storage.log
├── ├──  file syslog
├── ├──  file X.log
├──  directory audit
├── ├──  file audit.log
├──  file boot.log
├──  file boot.log-20240324
........

函数库文件

示例:

        (1)创建库文件

[root@openEuler ~]# cat function_library.sh 
#!/bin/bashaddition() {echo $[$1 + $2]
}substraction() {echo $[$1 - $2]
}multipication() {echo $[$1 * $2]
}division() {if [ $2 -eq 0 ]; thenecho "Division cannot be 0"elseecho $[$1 / $2]fi
}factorial() {if [ $1 -eq 1 ]; thenecho 1elif [ $1 -gt 1 ]; thenlocal tmp=$[$1-1]local res=$(factorial $tmp)echo $[$1 * res]elseecho "input value invalid"fi
}

        (2)在脚本中加载函数库文件并且使用

[root@openEuler ~]# cat fl_test.sh 
#!/bin/bash# load function_library.sh
source /root/function_library.shv1=10
v2=5r1=$(addition $v1 $v2)
r2=$(substraction $v1 $v2)r3=$(factorial $v2)echo $r1
echo $r2
echo $r3[root@openEuler ~]# bash fl_test.sh 
15
5
120

数组

        所谓数组,就是指将具有相同类型的若干变量按照一定的顺序组织在一起的一种数据类型

定义数组语法

用小括号将变量值括起来赋值给数组变量,每个变量之间用空格分隔array=(value1 value2 value3 ...... valuen)
使用小括号将变量值括起来,并且采用键值对的形式赋值array=([0]=one [1]=two ...... [n-1]=valuen)
分别定义数组变量的值array[0]=one;array[1]=two;......array[n]=valuen
使用动态的定义变量,并使用命令的输出结果作为数组的内容array=(命令)
通过 declare 语句来定义数组declare -a array

数组操作

获取所有元素

# 声明数组,数组的名称为 array,它里面有 6 个元素,分别是 1,2,3,4,5,6
[root@openEuler ~]# array=(1 2 3 4 5 6)
# 获取数组所有无素,需要注意使用大括号将整个数组包起来
[root@openEuler ~]# echo $array[*]
1[*]
[root@openEuler ~]# echo ${array[*]}
1 2 3 4 5 6
[root@openEuler ~]# echo ${array[@]}
1 2 3 4 5 6

获取元素下标

# 定义数组,数组的名称为 array,它的第一个元素是 hello,第二个元素是 shell,第三个元素是 python
[root@openEuler ~]# array=([0]="hello" [1]="shell" [2]="python")
# 通过 !数组名称[*|@] 来获取元素对应的下标
[root@openEuler ~]# echo ${!array[@]}
0 1 2
[root@openEuler ~]# echo ${!array[*]}
0 1 2

获取数组长度

# 定义数组,使用的是第三种语法
[root@openEuler ~]# array[0]="zhangsan"; array[1]="lisi"; array[2]="wangwu"
# 获取数组中第一个元素的长度
[root@openEuler ~]# echo ${#array}
8
# 获取数组元素个数(数组长度)
[root@openEuler ~]# echo ${#array[*]}
3
[root@openEuler ~]# echo ${#array[@]}
3

获取数组元素

# 使用第四种语法:数组名称=(命令) 来创建数组,然后通过下标获取对应的元素
[root@openEuler ~]# array=(`seq 5`)
# 获取数组中所有元素
[root@openEuler ~]# echo ${array[*]}
1 2 3 4 5
# 获取数组中下标为 3 所对应的元素,如果存在则返回该下标对应的元素,如果不存在则返回空
[root@openEuler ~]# echo ${array[3]}
4
[root@openEuler ~]# echo ${array[6]}[root@openEuler ~]# echo $?
0

数组添加元素

# 使用第五种语法来定义数组,数组的名称为 array
[root@openEuler ~]# declare -a array
# 给数组下标为0的位置添加元素
[root@openEuler ~]# array[0]=50
# 给数组下标为1的位置添加元素
[root@openEuler ~]# array[1]=35
# 给数组下标为2的位置添加元素
[root@openEuler ~]# array[20]=28
# 获取数组中所有元素
[root@openEuler ~]# echo ${array[*]}
50 35 28# 使用 -A 的方式来定义数组
[root@openEuler ~]# declare -A arr
[root@openEuler ~]# arr[one]=15
[root@openEuler ~]# arr[two]=20
[root@openEuler ~]# arr[thr]=30
[root@openEuler ~]# echo ${arr[@]}
30 20 15# 获取下标对应的元素
[root@openEuler ~]# echo ${array[1]}
35
[root@openEuler ~]# echo ${arr[two]}
20

删除数组元素

# 定义数组
[root@openEuler ~]# array=(10 20 30 40 50)
# 获取数组中所有元素
[root@openEuler ~]# echo ${array[@]}
10 20 30 40 50
# 删除数组中下标为2的元素
[root@openEuler ~]# unset array[2]
# 验证是否已经删除
[root@openEuler ~]# echo ${array[*]}
10 20 40 50
[root@openEuler ~]# echo ${#array[*]}
4

删除数组

# 定义数组
[root@openEuler ~]# array=(10 20 30 40 50)
# 获取数组长度
[root@openEuler ~]# echo ${#array[*]}
5
# 删除数组
[root@openEuler ~]# unset array
# 验证数组是否删除
[root@openEuler ~]# echo ${#array[@]}
0

遍历数组元素

[root@openEuler ~]# cat array.sh
#!/bin/bashfiles=(`ls $1`)
for((i=0;i<${#files[*]};i++)); doecho ${files[$i]}
done[root@openEuler ~]# bash array.sh 
array.sh
fact.sh
fl_test.sh
fun1.sh
fun2.sh
fun3.sh
fun4.sh
fun5.sh
fun6.sh
fun7.sh
function_library.sh
ips
myfile
mytest.sh
recursion2.sh
recursion.sh

数组案例

示例1:

        从标准输入读取 n 次字符串,每次输入的字符串保存在数组 array 中

[root@openEuler ~]# cat array1.sh 
#!/bin/bash
i=0
n=5
while [ "$i" -lt $n ]; doecho "Please input string... `expr $i + 1`"read array[$i]b=${array[$i]}echo "$b"i=`expr $i + 1`
done
[root@openEuler ~]# bash array1.sh 
Please input string... 1
1
1
Please input string... 2
2
2
Please input string... 3
3
3
Please input string... 4
4
4
Please input string... 5
5
5

示例2:

        将字符串中的字母逐个放入数组,并输出到标准输出

#!/bin/bashstrs="helloworldshell"
declare -a arrayfor ((i=0;i<${#strs};i++)); doarray[$i]=${strs:$i:1}
donefor i in ${array[@]}; doecho ${i}
done

示例3:

        将1~3这3个数字存到数组中,分别乘以8后再依次输出

#!/usr/bin/basharray=(`seq 3`)for ((i=0; i<${#array[@]}; i++)); doecho $[${array[$i]}*8]
done

示例4:

        输出如下内容中字母数不大于6的单词

cat is favorite to eat fish

#!/bin/basharray=(cat is favorite to eat fish)for i in ${array[*]}; doif [ ${#i} -le 6 ]; thenecho $ifi      
done

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

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

相关文章

解决pycharm无法识别miniconda

解决pycharm无法识别miniconda 找到miniconda安装目录下condabin/conda.bat文件&#xff0c;点击load即可识别codna环境 a环境

Spring Boot(七十九):SprngBoot整合Apache tika做文件类型检测

之前有一个章节介绍了Apache tika实现文档内容解析,地址如下:Spring Boot(六十八):SpringBoot 整合Apache tika 实现文档内容解析_springboot tika pptx-CSDN博客 下面我们介绍Apache tika实现文件类型检测 1 引入依赖 <dependency><groupId>org.apache.tika&…

Docker 挂载目录空间占满修改/var/lib/docker/overlay2 的路径解决方案

本文详细描述了在CentOS7系统中卸载旧版Docker、安装依赖、添加Docker源、配置存储路径并启动Docker&#xff0c;使其在/home目录下运行的过程。 以下是在CentOS 7下重新安装Docker并将其安装在/home/下的完整步骤&#xff1a; 卸载旧版本的Docker。如果您之前已经安装了Dock…

仕考网:没有学位证能考公务员吗?

公务员考试需要满足报名条件才能参加&#xff0c;没有学位证能考公吗? 没有学位证书的考生也有机会参与公务员考试虽然可以选择的岗位比较少&#xff0c;但可以报考参加那些不设定学位要求的岗位。当发布的公务员招录信息中某一职位的学位要求标注为“无要求”时&#xff0c;…

【C++】:继承[下篇](友元静态成员菱形继承菱形虚拟继承)

目录 一&#xff0c;继承与友元二&#xff0c;继承与静态成员三&#xff0c;复杂的菱形继承及菱形虚拟继承四&#xff0c;继承的总结和反思 点击跳转上一篇文章&#xff1a; 【C】&#xff1a;继承(定义&&赋值兼容转换&&作用域&&派生类的默认成员函数…

MATLAB Gazebo联合仿真

准备仿真环境&#xff1a;在Gazebo中设置仿真场景&#xff0c;包括机器人模型、环境布局、传感器和执行器等。编写MATLAB脚本&#xff1a;在MATLAB中编写控制算法和数据处理脚本&#xff0c;用于接收Gazebo中的传感器数据&#xff0c;并生成控制命令。建立通信&#xff1a;通过…

DEBUG:jeston卡 远程ssh编程

问题 jeston 打开网页 gpt都不方便 而且只需要敲命令就行 解决 下载MobaXterm(window执行) liunx需要虚拟机 软件 远程快速复制命令

PHP文字ocr识别接口示例、人工智能的发展

全球在人工智能升级的大背景下&#xff0c;有一定规模的制造商开始大量部署人工智能机器人、系统&#xff0c;以此取代危险、简单和重复性的工作。各种人工智能技术的迅猛发展&#xff0c;正在驱动各行业就业市场发现变革。 京东物流大家并不陌生&#xff0c;京东快递机器人在…

vue中table内容和lable对不齐解决方案

问题&#xff1a; 代码片段&#xff1a; <template><el-table :data"tableData" stripe style"width: 100%"><el-table-column prop"title" label"标题" width"80px" /><el-table-column prop"n…

Windows安全日志导致环境内存占用过高

Windows 环境内存占用高不释放&#xff0c;目前遇到的常见情况如下&#xff1a; 情况一&#xff1a;JVM内存泄漏 这种网上的排查方式有很多&#xff0c;自行查阅即可 情况二&#xff1a;SQLserver内存配置过大 这种也是&#xff0c;从网上查找修改方式然后修改即可 情况三…

python的面向对象编程

为什么要面向对象编程&#xff1f; 伟大的领袖毛泽东曾说过&#xff1a;编程最大的敌人是重复。 最开始&#xff0c;在程序中写的一条条语句&#xff0c;在执行的时候会变成一条条指令交给CPU执行。这就是**“程序是指令的集合”** 。为了简化程序的设计&#xff0c;引入了函数…

WebPages 全局:深入解析现代网页设计与开发

WebPages 全局:深入解析现代网页设计与开发 引言 随着互联网技术的飞速发展,网页设计与开发已经成为了数字化时代的重要组成部分。从简单的文本和图像展示,到如今复杂的多媒体交互体验,网页设计经历了翻天覆地的变化。本文将深入探讨WebPages全局,包括网页设计的基本概念…

Defensor 4.5:构建数据资产为中心的安全运营体系

5月31日“向星力”未来数据技术峰会上&#xff0c;星环科技重磅发布数据安全管理平台 Defensor 4.5版本。新版本引入了以数据资产为中心的数据安全运营体系&#xff0c;通过智能化大模型技术&#xff0c;帮助企业快速、精准地识别核心重要资产&#xff1b;建设全局的数据安全策…

pytorch GPU cuda 使用 报错 整理

GPU 使用、报错整理 1. 使用指定GPU&#xff08;单卡&#xff09;1.1 方法1&#xff1a;os.environ[CUDA_VISIBLE_DEVICES]1.2 方法2&#xff1a;torch.device(cuda:2)1.3 报错1&#xff1a;RuntimeError: CUDA error: invalid device ordinal CUDA kernel errors might be asy…

MySQL学习记录 —— 십팔 常用程序和配置文件

文章目录 1、mysqld2、mysql常用命令介绍 3、配置文件语法 1、mysqld mysqld就是MySQL服务器&#xff0c;是一个多线程程序。对数据目录&#xff0c;即mysql的主要工作目录进行访问管理。当mysqld启动时&#xff0c;会侦听指定的端口&#xff0c;处理来自客户端程序的网络连接…

【vue教程】二. Vue特性原理详解

目录 回顾本章涵盖知识点Vue 实例和选项创建 Vue 实例Vue 实例的选项 Vue 模板语法插值表达式指令v-bindv-modelv-on 自定义指令创建自定义指令在模板中使用自定义指令自定义指令的钩子函数自定义指令的实例演示 指令注册局部注册指令过滤器 数据绑定和响应式原理响应式数据绑定…

Oracle逻辑备份

逻辑备份 expdp 备份恢复表空间 创建测试数据 # 创建表空间 create tablespace itpux01 datafile /oradata/fghsdb/itpux01.dbf size 100m autoextend off extent management local autoallocate segment space management auto; create tablespace itpux02 datafile /o…

编程题目积累(day5)

题目&#xff1a; 源数组a&#xff0c;将a中所有元素乘以2之后添加进a&#xff0c;则这个a就叫双倍数组&#xff0c;给你一个数组a&#xff0c;判断它是不是双倍数组&#xff0c;如果是则输出源数组&#xff0c;不是则输出空数组。 补充知识&#xff1a; python中枚举和字典…

OAuth 和 SSO 场景中的 URL 语法解析

OAuth 和 SSO 场景中的 URL 语法解析 在 OAuth 和 SSO (Single Sign-On) 场景中&#xff0c;URL 是一个关键组件&#xff0c;用于在客户端和服务器之间传递认证请求和响应。让我们深入解析这个 URL&#xff1a; https://api.commerce.ondemand.com/occ/oauth/authorize?resp…

【python数据结构精讲】双端队列

通过总结《流畅的Python》等书中的知识&#xff0c;总结Python中常用工具的方法。 deque&#xff0c;学名双端队列。 1. 常用方法 append()&#xff1a;队列尾部添加appendleft()&#xff1a;队首添加pop()&#xff1a;移除队列最后一个元素popleft()&#xff1a;移除队列第一…