Shell脚本学习-Shell函数

news2024/12/24 9:09:38

函数的作用就是将程序里多次被调用的相同代码组合起来(函数体),并为其取一个名字,即函数名。其他所有想重复调用这部分代码的地方都只需要调用这个名字就可以了。当需要修改这部分代码时候,只需要修改函数体内的这部分代码即可实现对所有调用的修改,也可以把函数独立地写在文件里,当需要调用函数时,再加载进来使用。

好处:

1)把相同的程序段定义成函数,可以减少程序代码量;

2)增加程序的可读性,易读性;

3)呈现程序的功能模块化,使得程序具备通用性(可移植性)。

语法:

function 函数名() {
    指令...
    return n
}


函数名() {
    指令...
    return n
}

执行:

1)执行不带参数的函数,直接输入函数名即可。

2)执行带参数的函数:

函数名  参数1  参数2

3)函数的执行必须要在执行的程序前面定义和加载。

4)Shell执行系统中各种程序的执行顺序:系统别名-》函数-》系统命令-》可执行文件。

5)函数执行的时候,会和调用它的脚本公用变量,也可以为函数设定局部变量及特殊位置参数。

6)函数体中的return语句会返回一个退出值(返回值)给调用函数的当前程序。

7)如果将函数存放在一个独立的文件中,被脚本加载使用的时候,需要使用source或者点号来加载。

8)在函数内一般使用local定义局部变量,这些变量离开函数后,就会消失。

9)Shell的位置参数($1/$2/$#/$*/$?/$@)都可以作为函数的参数来使用。

10)此时的父脚本的参数临时地被函数参数所掩盖或者隐藏。

11)$0 比较特殊,他仍然是父脚本的名称。

12)当函数执行完成时,原来的命令行脚本的参数即可恢复。

13)函数的参数变量是在函数体里面定义的。

示例1:

[root@vm1 scripts]# cat function01.sh
#!/bin/bash

chang(){
    echo "I am chang."
}

chun() {
    echo "I am chun."
}

chang  # 调用chang
chun   #调用chun
[root@vm1 scripts]#  sh function01.sh
I am chang.
I am chun.

示例2:

分离函数体和执行函数的脚本文件(更规范的方法)

首先是建立函数体脚本(默认不会执行函数)。

使用cat命令追加多行脚本,以将函数代码追加到系统的函数文件中,即/etc/init.d/functions。

注意的是:要将定义的函数放在return 0的上面。如果放在return 0语句的下面,将无法调用到oldboy函数。在/etc/init.d/functions系统函数文件中添加的函数将不起作用。

然后在编辑脚本:

[root@vm1 scripts]# cat function02.sh
#!/bin/bash
#
[ -f /etc/init.d/functions ] && . /etc/init.d/functions || exit 1

oldboy
[root@vm1 scripts]# sh function02.sh
I am oldboy

 

程序和函数分离的常见方法:

[root@vm1 scripts]# cat fun02.sh
#!/bin/bash

# 在函数文件中只定义函数
# 可以在该函数文件中定义更多的函数
fun_01(){
    echo "I am oldboy linux."
}


[root@vm1 scripts]# cat exec01.sh
#!/bin/bash
#
[ -f fun02.sh ] && . ./fun02.sh || exit 1

# 执行函数
fun_01

[root@vm1 scripts]# sh exec01.sh
I am oldboy linux.

说明:

1)在函数文件中可以定义多个函数。

2)我们可以创建单独的函数文件,然后加载这个函数文件,而不需要使用系统的函数文件/etc/init.d/functions。

3)这是一个比较规范的方法。

示例3:带参数的shell函数。

[root@vm1 scripts]# cat fun02.sh
#!/bin/bash

# 在函数文件中只定义函数
# 可以在该函数文件中定义更多的函数
fun_01(){
    echo "I am oldboy linux."
}

# 带参数的函数
fun_02(){
    echo "I am $1"
}


[root@vm1 scripts]# cat exec01.sh
#!/bin/bash
#
[ -f fun02.sh ] && . ./fun02.sh || exit 1

# 执行带参数的函数,这个$1本身是脚本的位置参数,但是$1占据的位置为函数的参数位置,现在它们重合了。
fun_02 $1

# 将changchunhua作为参数
[root@vm1 scripts]# sh exec01.sh changchunhua
I am changchunhua

 说明:

此时的父脚本的参数临时地被函数参数所掩盖或者隐藏。

案例:利用shell函数开发企业级URL检测脚本:

[root@vm1 scripts]# cat url_check.sh
#!/bin/bash

if [ $# -ne 1 ]
  then
    echo "USAGE: $0 URL"
    exit 1
fi


wget --spider --timeout 10 --tries=2 $1 &>/dev/null

if [ $? -eq 0 ]
  then
    echo "$1 is yes."
else
    echo "$1 is no."
fi

测试结果:

[root@vm1 scripts]# sh url_check.sh www.baidu.com
www.baidu.com is yes.

[root@vm1 scripts]# sh url_check.sh jd.com
jd.com is yes.


然后,我们再进行一次升级:

将检测的功能写成函数,并将函数传参转换成脚本命令行传参,判断任意指定的url是否存在异常。

[root@vm1 scripts]# cat url_check2.sh
#!/bin/bash

# 帮助函数
function usage(){
    echo "USAGE: $0 url"
    exit 1
}


# 检测URL函数
function check_url(){
  wget --spider --timeout 10 --tries=2 $1 &>/dev/null
  if [ $? -eq 0 ]
    then
      echo "$1 is yes."
  else
      echo "$1 is no."
  fi
}

# 主函数
function main(){
  if [ $# -ne 1 ]  # 如果传入的是多个参数,则打印帮助函数,提示用户。
    then
      usage
  fi

  check_url $1
}

main $*  # 这里的$*就是把命令行接受的所有参数作为函数参数传给函数的内部,是一种常用的手法

学习了函数以后,尽量将脚本功能模块化,每个模块实现一个功能,并且让脚本可以通用。

工作中使用的一些Shell脚本,有时间也是需要进行升级修改,将脚本功能模块化。

 

然后我们使用更加专业的显示输出:

[root@vm1 scripts]# cat url_check3.sh
#!/bin/bash

[ -f /etc/init.d/functions ] && . /etc/init.d/functions || exit 1

# 帮助函数
function usage(){
    echo "USAGE: $0 url"
    exit 1
}


# 检测URL函数
function check_url(){
  wget --spider --timeout 10 --tries=2 $1 &>/dev/null
  if [ $? -eq 0 ]
    then
      # echo "$1 is yes."
      action "$1 is yes." /bin/true
  else
      # echo "$1 is no."
      action "$1 is no." /bin/true
  fi
}

function main(){
  if [ $# -ne 1 ]
    then
      usage
  fi

  check_url $1
}

main $*  # 这里的$*就是把命令行接受的所有参数作为函数参数传给函数的内部,是一种常用的手法

执行结果:

[root@vm1 scripts]# sh url_check3.sh jd.com
jd.com is yes.                                             [  OK  ]

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

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

相关文章

【网络编程】select

主旨思想 首先要构造一个关于文件描述符的列表,将要监听的文件描述符添加到该列表中 调用一个系统函数(select),监听该列表中的文件描述符,直到这些描述符中的一个或者多个进行I/O操作时,该函数才返回 这个函数是阻塞函数对文件描…

vue 图片回显标签

第一种 <el-form-item label"打款银行回单"><image-preview :src"form.bankreceiptUrl" :width"120" :height"120"/></el-form-item>// 值为 https://t11.baidu.com/it/app106&fJPEG&fm30&fmtauto&…

一篇五分生信临床模型预测文章代码复现——Figure 10.机制及肿瘤免疫浸润(二)

之前讲过临床模型预测的专栏,但那只是基础版本,下面我们以自噬相关基因为例子,模仿一篇五分文章,将图和代码复现出来,学会本专栏课程,可以具备发一篇五分左右文章的水平: 本专栏目录如下: Figure 1:差异表达基因及预后基因筛选(图片仅供参考) Figure 2. 生存分析,…

语音合成是什么?如何进行语音合成TTS数据采集?

我们在上一篇讲到语音数据采集分为常见的两种语音数据采集类型&#xff0c;一个是语音识别数据&#xff08;ASR&#xff09;&#xff0c;另一个是语音合成&#xff08;TTS&#xff09;。这一期中&#xff0c;我们将介绍语音合成技术是什么&#xff0c;如何采集语音合成数据和制…

【有趣的设计模式】23 种设计模式详解和场景分析

前言 七大设计原则 1、单一原则&#xff1a;一个类只负责一个职责 2、开闭原则&#xff1a;对修改关闭&#xff0c;对扩展开放 3、里氏替换原则&#xff1a;不要破坏继承关系 4、接口隔离原则&#xff1a;暴露最小接口&#xff0c;避免接口过于臃肿 5、依赖倒置原则&#xff1…

完美解决ubuntu系统QtCreator无法输入中文

在Ubuntu18 上安装搜狗输入法&#xff0c;启用fcitx输入系统之后Qt Creator 无法输入中文&#xff0c;原因是缺少fcitx的支持库libfcitxplatforminputcontextplugin.so。解决办法 1 查找是否安装相关库 $ dpkg -L fcitx-frontend-qt5 | grep .so /usr/lib/x86_64-linux-gnu/qt…

语义检索系统【二】:基于无监督训练SimCSE+In-batch Negatives策略有监督训练的语义索引召回

搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术细节以及项目实战(含码源) 专栏详细介绍:搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术…

//编写程序数一下 1到 100 的所有整数中出现多少个数字9

//编写程序数一下 1到 100 的所有整数中出现多少个数字9 int main() {int i;int count 0;//用来计数for (int i 1; i < 100; i) {if (i % 10 9 || i / 10 9)count;}printf("1到 100 的所有整数中出现%d个数字9\n", count);

[openCV]基于拟合中线的智能车巡线方案V1

import cv2 as cv import os import numpy as np# 遍历文件夹函数 def getFileList(dir, Filelist, extNone):"""获取文件夹及其子文件夹中文件列表输入 dir&#xff1a;文件夹根目录输入 ext: 扩展名返回&#xff1a; 文件路径列表"""newDir d…

Day10-NodeJS和NPM配置

Day10-NodeJS和NPM 一 Nodejs 1 简介 Nodejs学习中文网:https://www.nodeapp.cn/synopsis.html Nodejs的官网:https://nodejs.org/ 概念:Nodejs是JavaScript的服务端运行环境.Nodejs不是框架,也不是编程语言,就是一个运行环境. Nodejs是基于chrome V8引擎开发的一套js代码…

mac电脑访问windows共享文件夹连接不上(设置445端口)

前提&#xff1a;首先需要保证mac和windows都在同一局域网内&#xff0c;如果不在肯定是连不上的&#xff0c;就不用往下看了。 事情是这样的&#xff0c;公司入职发了mac电脑&#xff0c;但是我是window重度用户&#xff0c;在折腾mac的过程中&#xff0c;有许多文件需要从wi…

当系统接口要加入新方法时,我真后悔没有早点学学Java设计模式

假设系统中有一个接口&#xff0c;这个接口已经被10个实现类实现了&#xff0c;突然有一天&#xff0c;新的需求来了&#xff0c;其中5个实现类需要实现同一个方法。然后你就在接口中添加了这个方法的定义&#xff0c;想着一切都很完美。 当你在接口和其中5个实现类中加完这个…

java(Collection类)

文章目录 Collection接口继承树Collection接口及方法判断删除其它 Iterator(迭代器)接口迭代器的执行原理 foreach循环Collection子接口1&#xff1a;ListList接口特点List接口方法List接口主要实现类&#xff1a;ArrayListList的实现类之二&#xff1a;LinkedListList的实现类…

【python】我用python写了一个可以批量查询文章质量分的小项目(纯python、flask+html、打包成exe文件)

web 效果预览&#xff1a; 文章目录 一、API 分析1.1 质量分查询1.2 文章url获取 二、代码实现2.1 Python2.11 分步实现2.12 一步完成2.13 完整代码 2.2 python html2.21 在本地运行2.22 打打包成exe文件2.23 部署到服务器 一、API 分析 1.1 质量分查询 先去质量查询地址&a…

处理nacos、tomcat、nginx日志增长过快问题

1.nacos日志清理 修改nacos-logback.xml 将日志级别改为error级&#xff0c;减少info级日志产生量 将<maxHistory>调整为2以下&#xff0c;将 <totalSizeCap>调整为2GB左右 比如&#xff1a; [rootiZ0jlapur4hqjezy8waee0Z logs]# ll -h total 2.1G -rw-r--r-…

mysql忘记密码重置密码步骤

1.使用管理员权限打开cmd窗口&#xff0c;winr后输入cmd&#xff0c;然后按CtrlShiftEnter. 2.停止mysql服务&#xff0c;如上图net stop mysql 3.找到mysql安装目录下的my.ini文件&#xff0c;使用管理员权限打开 4.在[mysqld]下面新增一行skip-grant-tables 5.启动mysql服务…

新的恶意软件 WikiLoader 针对意大利组织

研究人员发现了一种新的恶意软件&#xff0c;名为 WikiLoader 恶意软件。之所以这样命名&#xff0c;是因为它向维基百科发出请求&#xff0c;希望得到内容中包含 "The Free "字符串的响应。 WikiLoader 恶意软件的主要目标是意大利企业及组织。 WikiLoader 是一种…

微信到底可以添加多少好友?怎么避免加人频繁?

微信作为一款用户月活跃量超过10亿的社交聊天软件&#xff0c;已经成为人们生活中不可或缺的一部分。 微信好友上限1万个 01 不知道有没有小伙伴好奇&#xff0c;微信到底可以添加多少好友&#xff1f;正好这个话题也上热搜了&#xff0c;我们就来了解一下。 有网友表示&…

Android安卓实战项目(6)---健身运动 APP实现健身运动倒计时显示提醒(源码在文末)

Android安卓实战项目&#xff08;6&#xff09;—健身运动 APP实现健身运动倒计时&#xff08;源码在文末&#x1f415;&#x1f415;&#x1f415;&#xff09; 一.项目运行介绍 【bilibili演示】 https://www.bilibili.com/video/BV1414y167WH/?share_sourcecopy_web&…

接受平庸,特别是程序员

目录 方向一&#xff1a;简述自己的感受 方向二&#xff1a;聊聊你想怎么做 方向三&#xff1a;如何调整自己的心态 虽然清楚知识需要靠时间沉淀&#xff0c;但在看到自己做不出来的题别人会做&#xff0c;自己写不出的代码别人会写时还是会感到焦虑怎么办&#xff1f; 你是…