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

3.1.4. Shell 函数的知识与实践

4. Shell 函数的知识与实践

4.1 Shell 函数介绍

在讲解Shell 函数之前,先来回顾Linux系统中 alias 的作用。

[laoma@shell ~]$ ls -l --color=auto /home
total 4
drwx------. 3 devops  devops    78 Nov 29 13:56 devops
drwx------. 7 laoma   laoma   4096 Dec  6 11:50 laoma
drwx------. 6 student student  169 Nov 29 13:56 student
[laoma@shell ~]$ alias ll='ls -l --color=auto'
[laoma@shell ~]$ ll /home/
total 4
drwx------. 3 devops  devops    78 Nov 29 13:56 devops
drwx------. 7 laoma   laoma   4096 Dec  6 11:50 laoma
drwx------. 6 student student  169 Nov 29 13:56 student

函数也有类似于别名的作用,例如可简化程序的代码量,让程序更易读、易改、易用。

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

使用 Shell 函数的优势整理如下:

  • 把相同的程序段定义成函数,可以减少整个程序的代码量,提升开发效率。
  • 增加程序的可读性、易读性,提升管理效率。
  • 可以实现程序功能模块化,使得程序具备通用性(可移植性)。

对于Shell来说,Linux系统里的近2000个命令可以说都是Shell的函数,所以,Shell的函数也是很多的,这一点需要读者注意。

4.2 Shell 函数的语法

下面是Shell 函数的常见语法格式。

标准写法

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

简化写法1:不写()

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

简化写法2:不写function

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

4.3 Shell 函数的执行

Shell的函数分为最基本的函数和可以传参的函数两种,其执行方式分别说明如下。

  1. 执行不带参数的函数时,直接输人函数名即可(注意不带小括号)。

    格式如下:函数名

    有关执行函数的重要说明:

    • 执行Shell 函数时,函数名前的function和函数后的小括号都不要带。
    • 函数的定义必须在要执行的程序前面定义或加载。
    • Shell执行系统中各种程序的执行顺序为:系统别名->函数->系统命令->可执行文件
    • 函数执行时,会和调用它的脚本共用变量,也可以为函数设定局部变量及特殊位置参数。
    • 在Shell 函数里面,return命令的功能与exit类似,return的作用是退出函数,而exit是退出脚本文件。
    • return语句会返回一个退出值(即返回值)给调用函数的当前程序,而exit会返回一个退出值(即返回值)给执行程序的当前Shell。
    • 如果将函数存放在独立的文件中,被脚本加载使用时,需要使用source或来加载。
    • 在函数内一般使用local定义局部变量,这些变量离开函数后就会消失。
  2. 带参数的函数执行方法,格式如下:

    函数名 参数1 参数2
    

    函数后接参数的说明:

    • Shell 的位置参数($1、2…、2…、2#、∗、*、?及$@)都可以作为函数的参数来使用。
    • 此时父脚本的参数临时地被函数参数所掩盖或隐藏。
    • $0 比较特殊,它仍然是父脚本的名称。
    • 当函数执行完成时,原来的命令行脚本的参数即可恢复。
    • 函数的参数变量是在函数体里面定义的。

4.4 Shell 函数的基础实践

**示例1:**hello函数

[root@server bin 17:40:00]# cat fun1.sh
#!/bin/bash
function hello () {
echo "hello world"
}
hello[root@server bin 17:40:07]# bash fun1.sh
hello world[root@server bin 17:40:09]# hello
-bash: hello: 未找到命令
[root@server bin 17:40:26]# source fun1.sh 
hello world
[root@server bin 17:40:38]# hello
hello world# 函数必须先定义,后调用
[root@server bin 17:40:42]# cat fun1.sh
#!/bin/bash
hello
function hello () {
echo "hello world"
}[root@server bin 17:41:35]# bash fun1.sh
fun1.sh:行2: hello: 未找到命令

**示例2:**调用外部函数

[root@server bin 17:41:41]# cat >> mylib << 'EOF'
> function hello () {
> echo "hello world"
> }
> EOF[root@server bin 17:43:18]# cat fun1.sh 
#!/bin/bash
if [ -r mylib ];then
source mylib
hello
else
echo "mylib is not exist"
exit 1
fi[root@server bin 17:47:09]# bash fun1.sh 
hello world
[root@server bin 17:47:26]# hello
hello world

**示例3:**带参数的函数

[root@server bin 17:52:27]# cat fun1.sh 
#!/bin/bash
function print () {
if [ "$1" == "PASS" ];then
echo -e '\033[1;32mPASS\033[0;39m'
elif [ "$1" == "FAIL" ];thenecho -e '\033[1;31mFAIL\033[0;39m'
elif [ "$1" == "DONE" ];thenecho -e '\033[1;35mDONE\033[0;39m'
else
echo "Usage: print PASS|FAIL|DONE"
fi
}
read -p "请输入你想要打印的内容: " str
print $str[root@server bin 17:52:48]# bash fun1.sh 
请输入你想要打印的内容: PASS
PASS
[root@server bin 17:52:54]# bash fun1.sh 
请输入你想要打印的内容: HELL
Usage: print PASS|FAIL|DONE

**示例4:**hello函数

[root@server bin 17:53:47]# cat fun1.sh 
#!/bin/bash
function print () {
if [ "$1" == "PASS" ];then
echo -e '\033[1;32mPASS\033[0;39m'
elif [ "$1" == "FAIL" ];thenecho -e '\033[1;31mFAIL\033[0;39m'
elif [ "$1" == "DONE" ];thenecho -e '\033[1;35mDONE\033[0;39m'
else
echo "Usage: $0 PASS|FAIL|DONE"
fi
}
str=$2
print $str# 结果表明,脚本的第一个参数并没有传递给脚本内部函数。
[root@server bin 17:55:42]# bash fun1.sh PASS FAIL
FAIL# 结果表明,$0 仍然使用脚本名,而非函数名。
[root@server bin 17:55:26]# bash fun1.sh 
Usage: fun1.sh PASS|FAIL|DONE

4.5 利用 Shell 函数开发企业级URL检测脚本

[root@server bin 17:56:01]# cat fun1.sh 
#!/bin/bash
function usage () {echo "usage: $0 url"exit 1
}function check_url () {wget --spider -q -o /dev/null --tries=1 -T 5 $1[ $? -eq 0 ] && echo $1 is accessable || echo $1 is not accessable
}function main () {[ $# -ne 1 ] && usagecheck_url $1
}main $*# 测试结果如下:
[root@server bin 17:59:35]# bash fun1.sh www.baidu.com
www.baidu.com is accessable
[root@server bin 18:01:37]# bash fun1.sh www.laoma.com
www.laoma.com is not accessable

4.6 函数的递归调用

示例1:求1+2+3+…+10 的和

#!/bin/bash
function sum_out() {if [ $1 -eq 1 ];thensum=1elsesum=$[ $1 + $(sum_out $[ $1 - 1 ] ) ]fiecho $sum
}
read -p "输入一个你想计算和的整数:" num
sum_out $num

示例2:求1*2*3*…*10 的阶乘

#!/bin/bash
function fact_out() {if [ $1 -eq 1 ];thensum=1elsesum=$[ $1 * $(fact_out $[ $1 - 1 ] ) ]fiecho $sum
}
read -p "输入一个你想计算和的整数:" num
fact_out $num

示例3:fork 炸弹

:(){ :|:& };:

解释如下:

:()   # 定义函数,函数名为":",即每当输入":"时就会自动调用{}内代码
{        # ":"函数起始字元:    # 用递归方式调用":"函数本身|    # 使用管道一次产生两个函数调用:    # 另一次递归调用的":"函数&    # 放后台运行,以便产生更多的子进程
}        # ":"函数终止
;        # ":"函数定义结束后将要进行的操作...
:        # 调用":"函数,"引爆"fork炸弹

fork 炸弹原因:无限制的启用新进程,直到消耗完所有计算资源。

解决办法:限制用户进程数量。

例如:限制100个进程

[laoma@shell ~]$ ulimit -u 100
http://www.dtcms.com/a/466244.html

相关文章:

  • 双目测距-初识
  • C++开发基础之日期处理的全面指南:从C库到Chrono
  • 北京网站维护公司直通车优化推广
  • 大厂MongoDB开发运维规范
  • 公司网站可以自己做吗wex5可以做网站吗
  • 在浏览器上播放摄像头rtsp视频流的实现方案
  • LeetCode算法日记 - Day 67: 不同路径、最长递增子序列
  • 2024ICPC区域赛香港站
  • 公司网站备案怎么做运营管理培训
  • 基于STM32的智能衣柜系统/智能衣帽间/wifi衣柜/wifi衣帽间/智能家居系统
  • access 网站后台seo引擎
  • 打字训练文章大全:哪吒打字1000篇打字文章素材
  • 使用 minimind
  • MinerU与Docling:智能文档处理框架对比
  • GAN(Generative Adversarial Nets)生成对抗网络论文笔记
  • sql练习
  • GESP C++等级认证三级12-操作string2-1
  • 人像摄影网站十大排名给公司建网站
  • 哈尔滨模板建站公司推荐上海传媒公司ceo是谁
  • Kubeadm安装完Kubernetes(K8S)后,ssh连不上了
  • 东方博宜OJ 1007:统计大写英文字母的个数 ← string
  • 3D地球可视化教程 - 第3篇:地球动画与相机控制
  • Python实现跳动的爱心
  • 网络营销策略存在的问题seo搜索引擎优化是做什么的
  • 中国建设银行门户网站wordpress 功能
  • 【ProtoBuffer】简介与安装
  • 网站管理 设置开启电子商务和网络购物网站
  • vue2和vue3响应式原理有何不同?
  • 做化工的 有那些网站沈阳网站排名工具
  • 郑州做网站的大公网站建设冫首先金手指十五