深入理解 Linux 函数参数

在Linux Shell编程中,函数是一种非常有用的功能,它可以将重复的代码封装起来,提高代码的可重用性和可维护性。在本文中,我们将探讨Linux Shell函数及其参数的相关知识。

函数基础

在Linux Shell中,我们可以使用 function 关键字定义一个函数,也可以使用 () 直接定义一个函数。函数定义的基本语法如下:

function_name() {command1command2...
}

或者

function function_name {command1command2...
}

以下是一个简单的函数示例:

#!/bin/bash# 定义函数
hello() {echo "Hello,World!"
}# 调用函数
hello

运行结果:

你好,世界!

函数参数

在Linux Shell中,函数可以接受参数,参数通过位置传递。函数内部使用 $1$2$3… 等来访问这些参数。$0 表示函数名,$# 表示传递给函数的参数个数,$@ 表示传递给函数的所有参数。

下面是一个使用函数参数的示例:

#!/bin/bash# 定义函数
print_info() {echo "函数名: $0"echo "第一个参数: $1"echo "第二个参数: $2"echo "所有参数: $@"echo "参数个数: $#"
}# 调用函数
print_info Hello World# 输出结果
# 函数名: print_info
# 第一个参数: Hello
# 第二个参数: World
# 所有参数: Hello World
# 参数个数: 2

参数解释

  • $0: 函数名。在上面的示例中,$0 的值为 print_info
  • $1$2$3…: 表示传递给函数的第一个、第二个、第三个…参数。在上面的示例中,$1 的值为 你好$2 的值为 世界
  • $#: 表示传递给函数的参数个数。在上面的示例中,$# 的值为 2。
  • $@: 表示传递给函数的所有参数,每个参数都作为单独的字符串。在上面的示例中,$@ 的值为 你好 世界

除了上述参数之外,还有一些其他的特殊参数,例如:

  • $*: 与 $@ 类似,也表示传递给函数的所有参数,但是会将所有参数作为一个整体,用双引号括起来。
  • $?: 函数的退出状态码,0表示成功,非0表示失败。
  • $$: 当前Shell进程的进程ID。

参数扩展

除了上述基本的参数之外,Linux Shell还提供了一些参数扩展功能,可以对参数进行一些操作和处理。以下是一些常用的参数扩展:

  • 删除前导和尾随空格:
    • ${parameter%/*word}: 删除parameter结尾的 /word
    • ${parameter%%/*word}: 删除parameter结尾的所有 /word
    • ${parameter#/*word}: 删除parameter开头的 /word
    • ${parameter##/*word}: 删除parameter开头的所有 /word
  • 替换字符串:
    • ${parameter/pattern/string}: 使用string替换parameter中第一次出现的pattern
    • ${parameter//pattern/string}: 使用string替换parameter中所有出现的pattern
    • ${parameter/#pattern/string}: 如果parameter以pattern开头,则用string替换pattern
    • ${parameter/%pattern/string}: 如果parameter以pattern结尾,则用string替换pattern
  • 字符串长度:
    • ${#parameter}: 返回parameter的长度
  • 默认值:
    • ${parameter:-word}: 如果parameter为空或未设置,则使用word作为其值
    • ${parameter:=word}: 如果parameter为空或未设置,则使用word作为其值,并将word赋给parameter
    • ${parameter:?word}: 如果parameter为空或未设置,则打印word作为错误消息,并退出shell
    • ${parameter:+word}: 如果parameter已设置且不为空,则使用word作为其值

这些参数扩展功能可以帮助我们更加灵活地处理函数参数,满足不同的需求。

进阶用法

$*

$* 表示传递给函数的所有参数,但会将所有参数作为一个整体,用双引号括起来。这意味着,如果你想要遍历所有参数,需要使用 "$*"$@ 的方式。示例如下:

#!/bin/bashprint_args() {echo "使用\$*输出参数: '$*'"echo "使用\$@输出参数: '$@'"for arg in "$@"; doecho "参数: $arg"done
}print_args foo "bar baz" qux# 输出结果:
# 使用$*输出参数: 'foo bar baz qux'
# 使用$@输出参数: 'foo bar baz qux'
# 参数: foo
# 参数: bar baz
# 参数: qux

在上面的示例中,我们可以看到 $* 将所有参数作为一个字符串输出,而 $@ 则将每个参数作为单独的字符串输出。当遍历参数时,需要使用 "$@" 的方式,以确保参数中包含空格时也能被正确处理。

$?

$? 表示函数或命令的退出状态码,0表示成功,非0表示失败。通常我们可以使用 $? 来检查函数或命令的执行结果,并根据结果进行相应的操作。示例如下:

#!/bin/bashmy_function() {echo "执行my_function..."return 1   # 返回非零状态码,表示失败
}my_function
result=$?if [ $result -eq 0 ]; thenecho "my_function执行成功"
elseecho "my_function执行失败,状态码为$result"
fi# 输出结果:
# 执行my_function...
# my_function执行失败,状态码为1

在上面的示例中,我们定义了一个 my_function 函数,并在函数内部使用 return 1 返回了一个非零状态码。然后,我们使用 $? 来检查函数的执行结果,并根据结果进行相应的操作。

补充内容

除了上述内容之外,我们还可以介绍一些其他方面的知识,例如:

  • 函数内部变量的使用:在函数内部,我们可以声明局部变量和全局变量。局部变量只在函数内部有效,而全局变量则在整个脚本中都可以访问。在函数内部修改全局变量时,可以使用 local 关键字声明一个新的同名局部变量,这样可以避免影响全局变量的值。示例如下:

    #!/bin/bashglobal_var="Hello"modify_global_var() {local global_var="World"echo "局部变量 global_var 的值为: $global_var"
    }echo "全局变量 global_var 的值为: $global_var"
    modify_global_var
    echo "修改后的全局变量 global_var 的值为: $global_var"
    

    运行结果:

    全局变量 global_var 的值为: Hello
    局部变量 global_var 的值为: World
    修改后的全局变量 global_var 的值为: Hello
    
  • 更多参数扩展的使用方法:除了介绍的参数替换和删除操作之外,我们还可以介绍一些其他参数扩展的使用方法,例如:

    • 使用通配符进行匹配和替换:可以使用通配符 *? 对字符串进行匹配和替换。示例如下:

      #!/bin/bashfile="example.txt"
      echo "文件名为: ${file}"
      echo "替换后的文件名为: ${file/txt/log}"
      

      运行结果:

      文件名为: example.txt
      替换后的文件名为: example.log
      
  • 编写更复杂的函数:我们可以介绍如何编写更复杂的函数,包括嵌套函数和递归函数等。嵌套函数指的是在一个函数内部定义另一个函数,而递归函数指的是在函数内部调用自身的函数。这些技巧可以帮助我们编写更加灵活和高效的Shell脚本。示例如下:

    #!/bin/bashouter_function() {inner_function() {echo "这是内部函数"}echo "这是外部函数"inner_function
    }outer_function
    

    运行结果:

    这是外部函数
    这是内部函数
    

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

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

相关文章

new mars3d.layer.GeoJsonLayer({的pupup配置参考

new mars3d.layer.GeoJsonLayer({的pupup配置可选项以及相关效果参考: 说明:popup按属性字段配置,可以是字符串模板或数组 1.popup仅配置{type}{name}等属性的的时候,指显示json文件内数据的type与name,效果如下 相关…

MyBatis核心配置文件:解锁数据之美的密码

MyBatis,这位编程的诗人,通过其独特的核心配置文件,为我们描绘出一幅数据之美的画卷。本篇博客将带你深入探讨MyBatis核心配置文件的奥秘,让你能够更好地理解和运用这个优雅的数据持久化框架。 最近想搞私域,欢迎各位…

【MySQL】8. 基本查询(update/delete/聚合/分组)

表的删改 3. Update 语法: UPDATE table_name SET column expr [, column expr ...] [WHERE ...] [ORDER BY ...] [LIMIT ...]对查询到的结果进行列值更新 案例: 3.1 将孙悟空同学的数学成绩变更为 80 分 -- 更新值为具体值 -- 查看原数据 SELECT…

开发指南-1:编码技巧与规范开始

目录 实例 1.使用对象代替if及switch 2.使用Array.from快速生成数组 3.使用router.beforeEach来处理跳转前逻辑 4.使用v-if来优化页面加载 5.路由跳转尽量使用name而不是path 6.使用key来优化v-for循环 7.使用computed代替watch 8.统一管理缓存变量 9.使用setTimeout…

【深度学习】训练Stable Diffusion环境

仓库: https://github.com/bmaltais/kohya_ss.git 基础镜像: from kevinchina/deeplearning:sdxllighting_trt_nginx_002api docker run --net host --gpus device0 -e APIWORKS1 -it t1:t1 bash构建环境: sudo -i git clone https://git…

springboot291校园疫情防控系统

校园疫情防控系统的设计与实现 摘 要 如今社会上各行各业,都喜欢用自己行业的专属软件工作,互联网发展到这个时候,人们已经发现离不开了互联网。新技术的产生,往往能解决一些老技术的弊端问题。因为传统校园疫情防控信息管理难度…

【Python难点答疑】2、为什么要有@classmethod和@staticmethod,有什么区别?

在 Python 中,staticmethod 和 classmethod 都是用来定义类中的特殊方法的装饰器。它们允许我们定义与类相关的方法,而不需要实例化类。虽然它们都允许我们在类中定义方法,但它们的行为和用法略有不同。 1.静态方法(staticmethod&…

Source Insight关于复制一段代码会自动添加空格或者Tab键的配置取消

Source Insight关于复制一段代码会自动添加空格或者Tab键的配置取消,这个情况在我们复制代码的时候对格式非常不友好,解决办法如下。 如下,我们可以设置相关配置: 设置完成后,然后再去复制,可以看到就没有相…

网络编程:包头分析

一、以太网头 以太网中封装了源mac地址以及目的mac地址,还有ip类型,以太网又称为mac头 0X0800 只接收发往本机的mac的ipv4类型的数据帧 0X0806 只接收发往本机的ARP类型的数据帧 0x8035 只接受发往本机的RARP类型的数据帧 0X0003 接收发往本机的MAC所…

【兆易创新GD32H759I-EVAL开发板】IPA与TLI 图层混合的区别

在GD32H7系列中,IPA(Image Processing Algorithm)和TLI(TFT LCD接口)都支持图层混合功能,提供了丰富的人机界面(HMI)显示能力。尽管这两个特性在图层混合方面有一定的相似性&#xf…

十八、软考-系统架构设计师笔记-真题解析-2022年真题

软考-系统架构设计师-2022年上午选择题真题 考试时间 8:30 ~ 11:00 150分钟 1.云计算服务体系结构如下图所示,图中①、②、③分别与SaaS、PaaS、IaaS相对应,图中①、②、③应为( )。 A.应用层、基础设施层、平台层 B.应用层、平台层、基础设施层 C.平…

Jenkins 一个进程存在多个实例问题排查

Jenkins 一个进程存在多个实例问题排查 最近Jenkins升级到2.440.1​版本后,使用tomcat​服务部署,发现每次定时任务总会有3-4个请求到我的机器人上,导致出现奇奇怪怪的问题。 问题发现 机器人运行异常,总有好几个同时请求的服务。…

C++ 模板入门详解

目录 0. 模板引入 1.函数模板 1. 函数重载的缺点 2. 函数模板的概念和格式 2. 函数模板的实例化 2.1 隐式实例化&#xff1a;让编译器根据实参推演模板参数的实际类型 2.2 显式实例化&#xff1a;在函数名后的<>中指定模板参数的实际类型 2.3 函数模板参数的匹…

return code 1 from org.apache.hadoop.hive.ql.ddl.DDLTask

Bug信息 Error: Error while compiling statement: FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.ddl.DDLTask (state=08S01,code=1)Bug产生的代码 修复hive表分区: msck repair table xxxBug原因排查 分区数量过大 这个是网上查看的说如果一次…

单身狗誓必脱单协会群(单身男女可进)

甜甜的恋爱&#xff0c;单身男女可进&#xff0c;谢绝己婚人士和海王进入&#xff01; 发送内容: "单身人士", 申请进群

【C++】—— 装饰器模式

目录 &#xff08;一&#xff09;什么是装饰器模式 &#xff08;二&#xff09;为什么要使用装饰器模式 &#xff08;三&#xff09;装饰器模式的实现步奏 &#xff08;四&#xff09;代码示例 &#xff08;五&#xff09;装饰器模式优缺点 &#xff08;一&#xff09;什么…

centos firewalld 封禁某个ip

在 CentOS 系统上使用 firewalld 封禁某个 IP 地址的步骤如下: 1. 确保 firewalld 已安装并运行: systemctl status firewalld 如果没有运行,启动 firewalld: systemctl start firewalld systemctl enable firewalld 2. 使用 firewall-cmd 命令临时封禁IP: firewall-cmd -…

【JavaSE】封装——访问修饰符详解

前言 我本来想着在【类与对象】那篇博客里讲访问修饰符的&#xff0c;但是因为继承还没有讲&#xff0c;protectded解释起来就会很费劲&#xff0c;就索性把【继承和多态】先写了&#xff0c;完了之后再来讲这个访问修饰符 访问修饰符 又称权限修饰符&#xff0c;我们之前见…

安科瑞保护测控产品在新能源行业中应用【峰谷套利 动态扩容 需求侧响应】

背景 2 月 10 日发布《关于完善能源绿色低碳转型体制机制和措施的意见》明确&#xff0c;鼓励建设源网荷储一体化、多能互补的智慧能源系统和微电网。 分布式光伏优势 近年来&#xff0c;随着光伏产业规模不断扩大&#xff0c;技术迭代升级不断加快&#xff0c;智能制造迅速推…

linux脚本中以yyyymmdd格式输出指定文件的修改日期

在Linux脚本中,你可以使用stat命令来查看文件的修改日期。然后,你可以使用date命令来格式化这个日期。以下是一个简单的bash脚本示例,它接受一个文件名作为参数,并打印出该文件的修改日期(以yyyymmdd格式): #!/bin/bash # 检查是否提供了文件名作为参数 if [ "…