当前位置: 首页 > news >正文

linux shell 函数

脚本函数基础

创建函数

在 bash shell 脚本中创建函数的语法有两种。第一种语法是使用关键字 function,随后跟上分配给该代码块的函数名:

function name {commands
}

name 定义了该函数的唯一名称。脚本中的函数名不能重复。

commands 是组成函数的一个或多个 bash shell 命令。调用该函数时,bash shell 会依次执行函数内的命令,就像在普通脚本中一样。

第二种在 bash shell 脚本中创建函数的语法更接近其他编程语言中定义函数的方式:

name() {commands
}

函数名后的空括号表明正在定义的是一个函数。这种语法的命名规则和第一种语法一样。

使用函数

#!/bin/bash
# using a function in a script
function func1 {echo "This is an example of a function"
}
count=1
while [ $count -le 5 ]
dofunc1count=$[ $count + 1 ]
done
echo "This is the end of the loop"
func1
echo "Now this is the end of the script"

函数定义不一定非要放在 shell 脚本的最开始部分,但是要注意这种情况。如果试图在函数被定义之前调用它,则会收到一条错误消息。

函数返回值

bash shell 把函数视为一个小型脚本,运行结束时会返回一个退出状态码,有 3 种方法能为函数生成退出状态码。

默认的退出状态码

在默认情况下,函数的退出状态码是函数中最后一个命令返回的退出状态码。函数执行结束后,可以使用标准变量$?来确定函数的退出状态码:

#!/bin/bash
# testing the exit status of a function
func1() {echo "trying to display a non-existent file"ls -l badfile
}
func2() {ls -l badfileecho "trying to display a non-existent file"
}
echo "testing the function: "
func1
echo "The exit status is: $?"
func2
echo "The exit status is: $?"

该函数的退出状态码是函数内部最后一条命令执行返回做的状态,上例中func1返回的状态是1(badfile不存在),func2返回的状态是0(最后一条命令执行成功)

使用return命令

bash shell 会使用 return 命令以特定的退出状态码退出函数。return 命令允许指定一个整数值作为函数的退出状态码,从而提供了一种简单的编程设定方式:

#!/bin/bash
# using the return command in a function
function dbl {read -p "Enter a value: " valueecho "doubling the value"# 函数执行一结束就立刻读取返回值。return $[ $value * 2 ]  # 退出状态码必须介于 0~255
}
dbl
echo "The new value is $?"

使用函数输出

正如可以将命令的输出保存到 shell 变量中一样,也可以将函数的输出保存到 shell 变量中:

result=$(dbl)

#!/bin/bash
# using the echo to return a value
function dbl {read -p "Enter a value: " valueecho $[ $value * 2 ]
}
result=$(dbl) # 注意,result获取的不是dbl执行的状态码# 而是最后一行命令输出的内容echo $[ $value * 2 ]
echo "The new value is $result"

新函数会用 echo 语句来显示计算结果。该脚本会获取 dbl 函数的输出,而不是查看退出状态码。

在函数中使用变量

向函数传递参数

函数可以使用标准的位置变量来表示在命令行中传给函数的任何参数。例如,函数名保存在$0 变量中,函数参数依次保存在$1、$2 等变量中。也可以用特殊变量$#来确定传给函数的参数数量。

在脚本中调用函数时,必须将参数和函数名放在同一行,就像下面这样:

func1 $value 10

#!/bin/bash
# passing parameters to a function
function addem {if [ $# -eq 0 ] || [ $# -gt 2 ]thenecho -1elif [ $# -eq 1 ]thenecho $[ $1 + $1 ]elseecho $[ $1 + $2 ]fi
}
echo -n "Adding 10 and 15: "
value=$(addem 10 15)
echo $value
echo -n "Let's try adding just one number: "
value=$(addem 10)
echo $value
echo -n "Now try adding no numbers: "
value=$(addem)
echo $value
echo -n "Finally, try adding three numbers: "
value=$(addem 10 15 20)
echo $value

在函数中处理变量

全局变量是在 shell 脚本内任何地方都有效的变量。如果在脚本的主体部分定义了一个全局变量,那么就可以在函数内读取它的值。

在默认情况下,在脚本中定义的任何变量都是全局变量。在函数外定义的变量可在函数内正常访问:

#!/bin/bash
# using a global variable to pass a value
function dbl {value=$[ $value * 2 ]
}read -p "Enter a value: " value
dbl
echo "The new value is: $value"

$value 变量在函数外定义并被赋值。当 dbl 函数被调用时,该变量及其值在函数中依然有效。如果变量在函数内被赋予了新值,那么在脚本中引用该变量时,新值仍可用。

局部变量:无须在函数中使用全局变量,任何在函数内部使用的变量都可以被声明为局部变量。只需在变量声明之前加上 local 关键字即可:

local temp

也可以在变量赋值语句中使用 local 关键字:

local temp=$[ $value + 5 ]

local 关键字保证了变量仅在该函数中有效。如果函数之外有同名变量,那么 shell 会保持这两个变量的值互不干扰。

#!/bin/bash
# demonstrating the local keyword
function func1 {local temp=$[ $value + 5 ]result=$[ $temp * 2 ]
}
temp=4
value=6func1
echo "The result is $result"
if [ $temp -gt $value ]
thenecho "temp is larger"
elseecho "temp is smaller"
fi

数组变量和函数

向脚本函数传递数组变量的方法:先将数组变量拆解成多个数组元素,然后将这些数组元素作为函数参数传递。最后在函数内部,将所有的参数重新组合成一个新的数组变量。

#!/bin/bash
# array variable to function test
function testit {local sum=0local newarraynewarray=(`echo "$@"`)echo "The new array value is: ${newarray[*]}"for value in ${newarray[*]}dosum=$[ $sum + $value ]doneecho $sum
}myarray=(1 2 3 4 5)
echo "The original array is ${myarray[*]}"
testit ${myarray[*]}

$myarray变量保存所有的数组元素,然后将其作为参数传递给函数。该函数随后根据参数重建数组变量。

函数向 shell 脚本返回数组变量:函数先用 echo 语句按正确顺序输出数组的各个元素,然后脚本再将数组元素重组成一个新的数组变量:

#!/bin/bash
# returning an array value
function arraydblr {local origarraylocal newarraylocal elementslocal iorigarray=($(echo "$@"))newarray=($(echo "$@"))elements=$[ $# - 1 ]for (( i = 0; i <= $elements; i++ )){newarray[$i]=$[ ${origarray[$i]} * 2 ]}echo ${newarray[*]}
}
myarray=(1 2 3 4 5)
echo "The original array is: ${myarray[*]}"
arg1=$(echo ${myarray[*]})
result=($(arraydblr $arg1))
echo "The new array is: ${result[*]}"

该脚本通过$arg1 变量将数组元素作为参数传给 arraydblr 函数。arraydblr 函数将传入的参数重组成新的数组变量,生成该数组变量的副本。然后对数据元素进行遍历,将每个元素的值翻倍,并将结果存入函数中的数组变量副本。

创建库

bash shell 允许创建函数库文件,然后在多个脚本中引用此库文件。

定义函数库文件 myfuncs.sh

# my script functions
function addem {echo $[ $1 + $2 ]
}
function multem {echo $[ $1 * $2 ]
}
function divem {if [ $2 -ne 0 ]thenecho $[ $1 / $2 ]elseecho -1fi
}

在需要用到这些函数的脚本文件中包含 myfuncs 库文件

使用函数库的关键在于 source 命令。source 命令会在当前 shell 的上下文中执行命令,而不是创建新的 shell 并在其中执行命令。可以用 source 命令在脚本中运行库文件。这样脚本就可以使用库中的函数了。

source 命令有个别名,称作点号操作符,可以用“点”代替

#!/bin/bash
# using a library file the wrong way
# 引入函数库
# source ./myfuncs 
# 引入函数库 推荐写法
. ./mufuncs # 注意点后面的空格
result=$(addem 10 15)
echo "The result is $result"

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • STM32控制机械臂与传感器:整合ESP32通讯、Spark与人工智能优化的智能制造解决方案(代码说明)
  • 机器学习第五章-神经网络
  • ubantu-elasticsearch
  • echarts横向柱状图
  • Vue3发送验证码,开启倒计时,并且倒计时结束前无法点击
  • 21LTR-Scene打靶渗透【附POC】(权限提升)
  • uniapp 多渠道打包实现方案
  • 【Buffer Pool】定长内存池的实现
  • cmake(1)
  • 【C++】:错误处理机制 -- 异常
  • 图像处理案例02
  • 效率何止10倍!利用输入法瞬间调用提示词
  • Harmony OS 卡片能力
  • ARM 离线安装k8s + harbor私有镜像库(麒麟)
  • NLP 之词的表示与语言模型
  • 【5+】跨webview多页面 触发事件(二)
  • bearychat的java client
  • C语言笔记(第一章:C语言编程)
  • IDEA常用插件整理
  • javascript 总结(常用工具类的封装)
  • JS 面试题总结
  • php ci框架整合银盛支付
  • Python进阶细节
  • swift基础之_对象 实例方法 对象方法。
  • vue2.0开发聊天程序(四) 完整体验一次Vue开发(下)
  • windows下使用nginx调试简介
  • 闭包--闭包之tab栏切换(四)
  • 当SetTimeout遇到了字符串
  • 聊一聊前端的监控
  • 用jQuery怎么做到前后端分离
  • ​补​充​经​纬​恒​润​一​面​
  • # Java NIO(一)FileChannel
  • # 透过事物看本质的能力怎么培养?
  • #我与Java虚拟机的故事#连载04:一本让自己没面子的书
  • #我与Java虚拟机的故事#连载06:收获颇多的经典之作
  • %3cli%3e连接html页面,html+canvas实现屏幕截取
  • (1)Jupyter Notebook 下载及安装
  • (3)(3.2) MAVLink2数据包签名(安全)
  • (5)STL算法之复制
  • (52)只出现一次的数字III
  • (Bean工厂的后处理器入门)学习Spring的第七天
  • (LNMP) How To Install Linux, nginx, MySQL, PHP
  • (二)什么是Vite——Vite 和 Webpack 区别(冷启动)
  • (分布式缓存)Redis分片集群
  • (九)One-Wire总线-DS18B20
  • (转)PlayerPrefs在Windows下存到哪里去了?
  • .Net 6.0--通用帮助类--FileHelper
  • .NET 8 跨平台高性能边缘采集网关
  • .net core 6 redis操作类
  • .NET 的程序集加载上下文
  • ::前边啥也没有
  • [100天算法】-不同路径 III(day 73)
  • [100天算法】-实现 strStr()(day 52)
  • [202209]mysql8.0 双主集群搭建 亲测可用
  • [ai笔记3] ai春晚观后感-谈谈ai与艺术