Linux shell编程 函数

news2024/11/18 3:35:28

shell函数的定义

function 函数名 {
    命令序列
}
函数名() {
  命令序列
}

函数的返回值

return表示退出函数并返回一个退出值,脚本中可以用$?变量显示该值

使用原则

1.函数一退出就取返回值,英文$?变量只会返回执行的最后一条指令的退出状态码

2.退出状态码必须是0-255,超出将会除以256取余

如何获取函数返回值(面试题) 

方法1.函数中return返回值,函数外执行函数,再 $? 获取函数执行结果。

          值必须0-255,超过取余 

方法2.函数中直接 echo 输出 ,函数外可以直接函数名调用输出结果。也可以调用函数并赋值给变量,再显示变量值(更好)。

#!/bin/bash

function test01 {
  read -p "请输入一个整数:" num
  return  $[num * 2] 
}

test01  #调用函数,根据返回值显示
echo $?
#!/bin/bash

function test02 {
  read -p "请输入一个整数:" num
  echo $[num * 2]
}

#直接输入函数名调用输出结果
test02
#或者赋值给变量再显示变量
result=$(test02)  # $(test02)  `test02` 获取命令结果
echo $result


函数传参

位置变量 $1 $2 $3......

#!/bin/bash

sum1() {
  sum=$[$1 + $2] #接收传参,根据传参的位置参数1 与位置参数2 相加
  echo $sum
}

read -p "输入第一个传入参数:" first #通过键盘读入参数赋值给变量
read -p "输入第二个传入参数:" second

sum1 $first $second #在调用函数时再使用变量作为传参

 位置变量搭配预定义变量$#(传参个数) $@(所有参数) $0(函数本身)

··········注意传参的位置参数!

#!/bin/bash

#定义函数
sum2() {
  #函数体内部的$1 $2 代表的是调用函数时,函数后面跟的位置参数
  sum=$[$1 - $2] #$1=200 $2=100 
  echo $sum
  echo "在函数体内部的\$#代表调用函数时,函数后面跟的参数个数,当前函数后面有$#个参数"
  echo "在函数体内部的\$@代表调用函数时,函数后面跟的所有参数,当前函数后面的参数有:$@"
  echo "在函数体内部,\$0代表$0"  #需要输出$0的文本,所以加上反斜杠 \ 避免$0被解释
}

echo "在函数体外时,\$#代表脚本后面跟的参数个数,当前脚本后面有$#个参数"
echo "在函数体外时,\$@代表脚本后面跟的所有参数,当前脚本后面参数有:$@"
echo "在函数体外,\$0代表$0"

#调用函数
#函数体外的$1 $2 代表的是执行脚本时,脚本后面跟的位置参数
sum2 $2 $1 #$2=200 $1=100 
[xue@xue ~]$ sh 2.sh 100 200 300 400 500
在函数体外时,$#代表脚本后面跟的参数个数,当前脚本后面有5个参数
在函数体外时,$@代表脚本后面跟的所有参数,当前脚本后面参数有:100 200 300 400 500
在函数体外,$0代表2.sh
100
在函数体内部的$#代表调用函数时,函数后面跟的参数个数,当前函数后面有2个参数
在函数体内部的$@代表调用函数时,函数后面跟的所有参数,当前函数后面的参数有:200 100
在函数体内部,$0代表2.sh

全局变量/局部变量

函数默认只能在脚本内的shell环境有效(使用source执行脚本会影响系统当前的shell环境)

脚本变量默认全局有效(即函数体内外都有效)

#!/bin/bash
myfun() {
  echo $name     #空 由于未定义name
  name=lisi
  echo $name     #lisi 
}

#####main######
myfun
echo $name       #lisi 由于变量默认是全局变量

执行local,可将变量限定在函数体内部局部变量

执行export,将变量变为全局变量(面试会问)

#!/bin/bash
myfun() {
  echo $name     #空 由于未定义name
  local name=lisi
  echo $name     #lisi 
}

#####main######
myfun
echo $name       #空 由于name设定为local局部变量

递归

可以使用for循环实现相同效果,但是递归的执行效率更高

 

递归求阶乘

#!/bin/bash
#使用函数的递归实现阶乘

jiecheng () {
  if [ $1 -eq 1 ];then #当递归传参=1时不再递归,返回1作为result,与传参$1相乘输出结果
    echo 1 
  elif [ $1 -gt 1 ];then
    local tmp=$[$1 - 1] #tmp作为局部变量用于技术,每次递归-1,=1停止递归
    local result=$(jiecheng $tmp) #递归调用
    echo $[$1 * result]
  else
    echo "输入的值无效。请输入大于等于1的整数!"
  fi
}


#####main#####
read -p "请输入一个大于等于1的整数:" num
result=$(jiecheng $num)
echo "$num的阶乘值为$result"


  

递归输出目录与文件

#!/bin/bash
#使用函数递归目录/var/log,如果是文件直接输出文件名
#如果是目录则输出目录名且输出此目录下的所有目录和文件名

listfolder () {
  for folder in $(ls $1)  #$(ls $1) ls用于获取文件遍历结果 $1位置变量获取需要遍历的路径
  do
    if [ -d "$1/$folder" ];then  #$1/$folder拼接完整路径,若是文件夹,$2增加空格,递归调用
      echo "$2目录$folder" #显示子文件夹 #此处$2用于在子文件夹前增加空格显示层次。
      listfolder "$1/$folder" "  $2"  #每迭代一次传参时都会增加两个两个空格。遍历子文件夹
    else                                 
      echo "$2文件$folder"  #文件加上 $2传来的空格,显示文件名
    fi
  done
}

listfolder "/var/log" "" 
#调用函数,第一个参数为文件夹路径,第二个参数为空,表示层次,若文件夹迭代则会增加空格显示

  

 

递归输出环境变量中目录和不可执行文件

#!/bin/bash
#通过脚本输出环境变量PATH所包含的所有目录以及其中的子目录和所有不可执行文件

#定义一个遍历PATH环境变量的函数
list_path() {
    IFSB=$IFS 
    IFS=$IFS':'       #由于$PATH获取的环境变量用 : 分隔,修改分隔符变量IFS 使:也识别为分隔符
    for F in $PATH
    do
        echo $F   #echo输出$PATH环境变量中的所有文件夹
    done
    IFS=$IFSB
}

#定义一个递归函数
listf() {
    for F in $(ls $1)
    do
        if [ -d "$1/$F" ];then
            echo "$2$F"
            listf "$1/$F" "  $2"
        else
            if [ ! -x "$1/$F" ];then
                echo "$2$F"
            fi
        fi
    done
}


######main######
folder=$(list_path) #调用list_path获取所有环境变量路径

for path in $folder
do                    #对每一条路径显示
    echo $path        #并且调用listf递归现实子文件夹和文件
    listf "$path" "  "
done

 

函数调用示例

多级调用函数将IP地址转为二进制

#!/bin/bash
#将一个点分十进制格式的IP地址转换成点分二进制格式
#比如 255.255.255.255   -->  11111111.11111111.11111111.11111111

#定义一个用于十进制转换为二进制的函数
switch_bin() {
    NUM=$1
    for i in {1..8}
    do
        SUM=$[NUM % 2]$SUM
        let NUM/=2
    done
    echo $SUM
}    

#定义一个用于分割IP的函数
SPT() {
    IP=$1 #获取传参IP
    for i in {1..4}  #IP四段循环四次
    do
        num=${IP%%.*}        #num从后向前删到最后一个点,每次循环只取第一段。
        IP=${IP#*.}          #IP 从前向后删到第一个点, 每次循环减去头部一段
        BIN=$(switch_bin num)#num为第一段取值,调用函数转换二进制
        echo -n $BIN.    #不换行输出转换结果( xxxxxxxx. )循环四次拼接四段
    done

}


#####main#####
read -p "请输入一个合法IP:" IP
result=$(SPT $IP)
echo ${result%.*} #去除最后一段的点( xxxxxxxx. → xxxxxxxx )

函数库

可以实现写好函数库,需要时直接调用,无需每次都写一遍函数

编写函数库

vim /opt/function
jiafa() {
    echo $[$1 + $2]
}

jianfa() {
    echo $[$1 -$2]
}

chengfa() {
    echo $[$1 * $2]
}

chufa() {
   if [ $2 -eq 0 ];then
       echo "除数不可为0"
   else
       echo $[$1 / $2]
   fi
}

jiecheng() {
  if [ $1 -eq 1 ];then
    echo 1
  elif [ $1 -gt 1 ];then
    local tmp=$[$1 - 1]
    local result=$(jiecheng $tmp)
    echo $[$1 * result]
  else
    echo "输入的值无效。请输入大于等于1的整数!"
  fi
}

调用函数库 

#!/bin/bash

#加载函数库文件到当前脚本的shell
. /opt/function
#source /opt/function = . /opt/function

value1=10
value2=5

result1=$(jiafa $value1 $value2)
result2=$(jianfa $value1 $value2)
result3=$(chengfa $value1 $value2)
result4=$(chufa $value1 $value2)
result5=$(jiecheng $value1 $value2)
# $(jiecheng $value1 $value2) =`jiecheng $value1 $value2`
 
echo "加法的结果为$result1"
echo "减法的结果为$result2"
echo "乘法的结果为$result3"
echo "除法的结果为$result4"
echo "阶乘的结果为$result5"
[root@xue opt]# sh 10.sh
加法的结果为15
减法的结果为5
乘法的结果为50
除法的结果为2
阶乘的结果为3628800

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

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

相关文章

基于Redis的Stream结构作为消息队列,实现异步秒杀下单

文章目录 1 认识消息队列2 基于List实现消息队列3 基于PubSub的消息队列4 基于Stream的消息队列5 基于Stream的消息队列-消费者组6 基于Redis的Stream结构作为消息队列,实现异步秒杀下单 1 认识消息队列 什么是消息队列:字面意思就是存放消息的队列。最…

2.4G无线麦克风无线音频传输模块

模块概述 M01主要是一个2.4G无线音频传输模块,模组RF电路设计配合独有的软件跳频机制,有效提高了RF的抗干扰能力及传输距离。模组内置高性能的音频转换器,支持48K/24bit高品质的音频采样、支持麦克风的主动降噪,实现了无压缩的数字…

设计模式:SOLID原则

单一职责原则 Single Responsibility Principle(SRP) 接口职责应该单一,不要承担过多的职责。 开放封闭原则 Open Closed Principle(OCP) 添加一个新的功能应该是,在已有代码基础上扩展代码(…

mysql——索引,一篇说清!

直观感受——数据准备 建表与插入数据 CREATE TABLE user (uid int(11) NOT NULL AUTO_INCREMENT,name varchar(50) DEFAULT NULL,pwd varchar(50) DEFAULT NULL,create_time datetime DEFAULT NULL,modify_time timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT…

VSCode For Web 深入浅出 -- 插件加载机制

最近我在浏览 VSCode for web 的 repo,在最近更新的一些 commit 中发现了一个新的 VSCode 插件特性支持,名为 webOpener,它的作用是什么呢?又是如何影响插件加载的呢?在这一篇中我们结合 VSCode For Web 的插件加载机制…

大项目准备(2)

目录 中国十大最具发展潜力城市 docker是什么?能介绍一下吗? 中国十大最具发展潜力城市 按照人随产业走、产业决定城市兴衰、规模经济和交通成本等区位因素决定产业布局的基本逻辑,我们在《中国城市发展潜力排名:2022》研究报告…

uniapp和小程序如何分包,详细步骤手把手(图解)

一、小程序分包 每个使用分包小程序必定含有一个主包。所谓的主包,即放置默认启动页面/TabBar 页面,以及一些所有分包都需用到公共资源/JS 脚本;而分包则是根据开发者的配置进行划分。 在小程序启动时,默认会下载主包并启动主包…

C++学习day--11 程序员必备工具--github

github 的重要性: 网络时代的程序员必备。 github 的作用: 1. 版本管理 2. 多人协作 3. 开源共享 常用方案: gitTortoiseGitgithub [Tortoise ,程序员常称其为小乌龟,小海龟 ] 安装配置步骤 1. 注册 h…

13 KVM虚拟机配置-配置虚拟设备(总线配置)

文章目录 13 KVM虚拟机配置-配置虚拟设备(总线配置)13.1 概述13.2 元素介绍13.3 配置示例 13 KVM虚拟机配置-配置虚拟设备(总线配置) 13.1 概述 总线是计算机各个部件之间进行信息通信的通道。外部设备需要挂载到对应的总线上&a…

MySQL调优系列(四)——执行计划

一、概述 sql语句是有具体的执行过程的,通过查看这个执行过程,可以针对性的优化某一步骤,以加快SQL语句的执行效率。 通过MySQL调优系列(一)——性能监控我们可以知道,有一个查询优化器,查询优…

HTTP第五讲——搭建HTTP实验环境

HTTP简介 HTTP 协议诞生于 30 年前,设计之初的目的是用来传输纯文本数据。但由于形式灵活,搭配URI、HTML 等技术能够把互联网上的资源都联系起来,构成一个复杂的超文本系统,让人们自由地获取信息,所以得到了迅猛发展。…

D. Petya and Array(树状数组 + 前缀和 + 逆序对的思想)

Problem - D - Codeforces Petya 有一个由 n 个整数组成的数组 a。他最近学习了部分和,现在他可以非常快地计算出数组中任何一段元素的和。这个段是一个非空的序列,相邻的元素排在数组中。 现在他想知道他的数组中元素和小于 t 的段的数量。请帮助 Pety…

鸿蒙Hi3861学习九-Huawei LiteOS(互斥锁)

一、简介 互斥锁又被称为互斥型信号量,是一种特殊的二值信号量,用于实现对共享资源的独占式处理。 任意时刻互斥锁的状态只有两种:开锁或闭锁。 当有任务占用公共资源时,互斥锁处于闭锁状态,这个任务获得该互斥锁的使用…

lua | 循环和函数的使用

目录 一、循环与流程控制 循环 流程控制 二、函数 函数 多返回值 可变参数 本文章为笔者学习分享 学习网站:Lua 基本语法 | 菜鸟教程 一、循环与流程控制 循环 lua语言提供了以下几种循环处理方式: 1.while 条件为true时,程序重复…

数据结构(六)—— 二叉树(7)构建二叉树

文章目录 如何使用递归构建二叉树1、创建一颗全新树(题1-5)2、在原有的树上新增东西(题6) 1 106 从 后序 与 中序 遍历序列构造二叉树2 105 从 前序 与 中序 遍历序列构造二叉树3 108 将有序数组转换为二叉搜索树(输入…

施耐德电气 × 牛客:HR如何助力业务数字化转型?

历经一百八十多年的发展,施耐德电气从一家钢铁企业,进入电力与控制领域,再到如今成为全球能源管理和自动化领域的数字化专家,业务覆盖100多个国家,拥有近13万员工。 其背后离不开HR强大后盾的支撑,下面将独…

Linux文件系统目录有什么用?

学习文件系统的意义在于文件系统有很多设计思路可以迁移到实际的工作场景中,比如: MySQL 的 binlog 和 Redis AOF 都像极了日志文件系统的设计;B Tree用于加速磁盘数据访问的设计,对于索引设计也有通用的意义。 特别是近年来分布…

【Java|golang】1010. 总持续时间可被 60 整除的歌曲

在歌曲列表中&#xff0c;第 i 首歌曲的持续时间为 time[i] 秒。 返回其总持续时间&#xff08;以秒为单位&#xff09;可被 60 整除的歌曲对的数量。形式上&#xff0c;我们希望下标数字 i 和 j 满足 i < j 且有 (time[i] time[j]) % 60 0。 示例 1&#xff1a; 输入&…

【LangChain】如何本地部署基于chatGPT的实时文档和表格数据的助手,在自己的数据上构建chatGPT?

【LangChain】如何本地部署基于chatGPT的实时文档和表格数据的助手&#xff0c;在自己的数据上构建chatGPT 1 相关技术 &#xff08;1&#xff09;LangChain 是一个用于自然语言处理的 Python 库&#xff0c;它的目标是尝试简化自然语言处理任务&#xff0c;提高处理效率和准…

渲染对电脑伤害大吗_如何减少渲染伤机?

虽然说摄影穷三代&#xff0c;但想要自己的本地配置跟上自己的创作速度&#xff0c;高昂的硬件配置支出也可以让自己穷一段时间。CG制作过程中&#xff0c;渲染是必不可少的一步&#xff0c;而且这一步也是很吃“机器”的&#xff0c;那很多人也会担心&#xff0c;如果经常用自…