Shell 函数入门:定义、传参与返回值

举报
yd_283162409 发表于 2026/11/12 08:29:32 2026/11/12
【摘要】 为什么需要 Shell 函数写 Shell 脚本时,经常会遇到同一段命令反复出现:检查服务状态、打一条带时间的日志、备份某个目录。复制粘贴三次还能忍,第五次就该收进函数里了。函数把一段命令打包成一个名字,以后只写名字就能调用,改逻辑也只改一处。两种定义写法最常见的写法是 name() { ...; },function 关键字可加可不加:say_hello() { echo "hello,...

为什么需要 Shell 函数

写 Shell 脚本时,经常会遇到同一段命令反复出现:检查服务状态、打一条带时间的日志、备份某个目录。复制粘贴三次还能忍,第五次就该收进函数里了。函数把一段命令打包成一个名字,以后只写名字就能调用,改逻辑也只改一处。

两种定义写法

最常见的写法是 name() { ...; },function 关键字可加可不加:

say_hello() {
  echo "hello, $1"
}
function say_hello {
  echo "hello, $1"
}

两种写法完全等价,用第一种的人更多。注意:函数必须先定义、后调用,脚本是自上而下执行的,在定义之前调用会报 command not found。

传参:位置参数

调用函数时跟在名字后面的就是参数,函数体内用位置参数接收:$1 是第一个参数,$2 是第二个,$@ 是全部参数,$# 是参数个数。注意这里的 $1 是函数的参数,不是脚本的参数,两者互不干扰:

backup() {
  echo "正在备份 $1 到 $2"
  cp -r "$1" "$2"
}
backup /etc/nginx /tmp/nginx.bak

参数一定要加双引号,否则带空格的路径会被拆成两个参数,这是新手最常踩的坑。

返回值:两种通道

函数有两种方式把结果交出来。第一种是退出状态码:return 0 表示成功,非零表示失败,调用方用 $? 读取。注意状态码只能是 0 到 255,return 300 会被截断:

is_root() {
  [ "$(id -u)" -eq 0 ]
}
if is_root; then
  echo "当前是 root"
fi

第二种是标准输出:函数里 echo 的内容,调用方用命令替换 $(...) 接住,适合返回字符串:

today() {
  date +%Y-%m-%d
}
echo "今天是 $(today)"

局部变量:别污染全局

函数里赋值的变量默认是全局的,函数外也能看到,容易互相踩。养成习惯:函数内部一律用 local 声明:

count_files() {
  local dir=$1
  local n=$(ls "$dir" | wc -l)
  echo "$n"
}

local 只能在函数体内用,写在函数外会报错。

一个顺手的例子:带时间戳的日志函数

log() {
  echo "[$(date '+%H:%M:%S')] $*"
}
log "开始部署"
log "部署完成"

脚本里所有关键步骤都走 log,出了问题按时间翻日志,一眼就能定位到哪一步卡住了。

小结

函数三件事:定义用 name() { },传参用 $1、$2、$@,返回结果用状态码或 echo。先把重复三遍以上的命令收进函数,再顺手加个 log 函数,你的脚本会立刻清爽很多。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。