格式:
select NAME [in WORDS ... ;] do COMMANDS; done select variable in list ;do 循环体命令 done
说明:
范例:
[root@rocky8 ~]# type select select is a shell keyword [root@rocky8 ~]# help select select: select NAME [in WORDS ... ;] do COMMANDS; done Select words from a list and execute commands. The WORDS are expanded, generating a list of words. The set of expanded words is printed on the standard error, each preceded by a number. If `in WORDS' is not present, `in "$@"' is assumed. The PS3 prompt is then displayed and a line read from the standard input. If the line consists of the number corresponding to one of the displayed words, then NAME is set to that word. If the line is empty, WORDS and the prompt are redisplayed. If EOF is read, the command completes. Any other value read causes NAME to be set to null. The line read is saved in the variable REPLY. COMMANDS are executed after each selection until a break command is executed. Exit Status: Returns the status of the last command executed. [root@rocky8 ~]# select menu in backup upgrade downgrade clean ;do true ;done 1) backup 2) upgrade 3) downgrade 4) clean #? 1 #? ^C [root@rocky8 ~]# PS3="请选择相关序号: " [root@rocky8 ~]# select menu in backup upgrade downgrade clean ;do true ;done 1) backup 2) upgrade 3) downgrade 4) clean 请选择相关序号: 1 请选择相关序号: ^C
范例:
[root@rocky8 ~]# vim select.sh #!/bin/bash # #********************************************************************************************** #Author: Raymond #QQ: 88563128 #Date: 2021-10-20 #FileName: select3.sh #URL: raymond.blog.csdn.net #Description: The test script #Copyright (C): 2021 All rights reserved #********************************************************************************************* PS3="请选择相关序号: " select menu in backup upgrade downgrade clean; do case $menu in backup) echo backup ;; upgrade) echo upgrade ;; *) echo other ;; esac done [root@rocky8 ~]# bash select.sh 1) backup 2) upgrade 3) downgrade 4) clean 请选择相关序号: 1 backup 请选择相关序号: 2 upgrade 请选择相关序号: 3 other 请选择相关序号: 4 other 请选择相关序号: ^C [root@rocky8 ~]# vim select.sh #!/bin/bash # #********************************************************************************************** #Author: Raymond #QQ: 88563128 #Date: 2021-10-20 #FileName: select.sh #URL: raymond.blog.csdn.net #Description: The test script #Copyright (C): 2021 All rights reserved #********************************************************************************************* PS3="请选择相关序号" select menu in backup upgrade downgrade clean exit; do case $REPLY in 1) echo backup ;; 2) echo upgrade ;; 3) echo downgrade ;; 4) echo clean ;; 5) exit ;; *) echo input flase ;; esac done [root@rocky8 ~]# bash select2.sh 1) backup 2) upgrade 3) downgrade 4) clean 5) exit 请选择相关序号1 backup 请选择相关序号5
范例:
[root@rocky8 ~]# vim select3.sh #!/bin/bash # #********************************************************************************************** #Author: Raymond #QQ: 88563128 #Date: 2021-10-20 #FileName: select2.sh #URL: raymond.blog.csdn.net #Description: The test script #Copyright (C): 2021 All rights reserved #********************************************************************************************* # sum=0 PS3="请点菜(1-6): " select MENU in 北京烤鸭 佛跳墙 小龙虾 羊蝎子 火锅 点菜结束;do case $REPLY in 1) echo $MENU 价格是 100 let sum+=100 ;; 2) echo $MENU 价格是 88 let sum+=88 ;; 3) echo $MENU价格是 66 let sum+=66 ;; 4) echo $MENU 价格是 166 let sum+=166 ;; 5) echo $MENU 价格是 200 let sum+=200 ;; 6) echo "点菜结束,退出" break ;; *) echo "点菜错误,重新选择" ;; esac done echo "总价格是: $sum" [root@rocky8 ~]# bash select3.sh 1) 北京烤鸭 2) 佛跳墙 3) 小龙虾 4) 羊蝎子 5) 火锅 6) 点菜结束 请点菜(1-6): 1 北京烤鸭 价格是 100 请点菜(1-6): 8 点菜错误,重新选择 请点菜(1-6): 5 火锅 价格是 200 请点菜(1-6): 6 点菜结束,退出 总价格是: 300
函数由两部分组成:函数名和函数体
帮助参看:help function
#语法一: func_name (){ ...函数体... } #语法二: function func_name { ...函数体... } #语法三: function func_name () { ...函数体... }
范例:
[root@rocky8 ~]# type function function is a shell keyword [root@rocky8 ~]# help function function: function name { COMMANDS ; } or name () { COMMANDS ; } Define shell function. Create a shell function named NAME. When invoked as a simple command, NAME runs COMMANDs in the calling shell's context. When NAME is invoked, the arguments are passed to the function as $1...$n, and the function's name is in $FUNCNAME. Exit Status: Returns success unless NAME is readonly. [root@rocky8 ~]# cd /etc/init.d/ [root@rocky8 init.d]# ls functions README [root@rocky8 init.d]# less functions
#查看当前已定义的函数名 declare -F #查看当前已定义的函数定义 declare -f #查看指定当前已定义的函数名 declare -f func_name #查看当前已定义的函数名定义 declare -F func_name
范例:
[root@rocky8 init.d]# hello () { echo "hello,function"; } [root@rocky8 init.d]# declare -f hello #-f 显示函数内容 hello () { echo "hello,function" } [root@rocky8 init.d]# declare -F hello #-F 显示函数名称 hello [root@rocky8 init.d]# declare -F declare -f gawklibpath_append declare -f gawklibpath_default declare -f gawklibpath_prepend declare -f gawkpath_append declare -f gawkpath_default declare -f gawkpath_prepend declare -f hello [root@rocky8 init.d]# hello hello,function
格式:
unset func_name
范例:
[root@rocky8 init.d]# unset hello [root@rocky8 init.d]# hello -bash: hello: command not found
函数的调用方式
调用:函数只有被调用才会执行,通过给定函数名调用函数,函数名出现的地方,会被自动替换为函数代码
函数的生命周期:被调用时创建,返回时终止
交互式环境下定义和使用函数
范例:
[root@rocky8 ~]# dir() { > ls -l > } [root@rocky8 ~]# dir total 116 -rw-------. 1 root root 1318 Oct 6 19:20 anaconda-ks.cfg
范例:实现判断CentOS的主版本
[root@rocky8 init.d]# centos_version() { > sed -rn 's#^.* +([0-9]+)\..*#\1#p' /etc/redhat-release > } [root@rocky8 init.d]# centos_version 8 root@ubuntu1804:~# ubuntu_version(){ > sed -rn '2s/^.*="([0-9]+)\..*/\1/p' /etc/os-release > } root@ubuntu1804:~# ubuntu_version 18
函数在使用前必须定义,因此应将函数定义放在脚本开始部分,直至shell首次发现它后才能使用,调用函数仅使用其函数名即可
范例:
[root@rocky8 ~]# vim test1.sh #!/bin/bash # #********************************************************************************************** #Author: Raymond #QQ: 88563128 #Date: 2021-10-21 #FileName: test1.sh #URL: raymond.blog.csdn.net #Description: The test script #Copyright (C): 2021 All rights reserved #********************************************************************************************* func1(){ echo func1 is runing } func1 [root@rocky8 ~]# bash test1.sh func1 is runing [root@rocky8 ~]# vim test1.sh #!/bin/bash # #********************************************************************************************** #Author: Raymond #QQ: 88563128 #Date: 2021-10-21 #FileName: test1.sh #URL: raymond.blog.csdn.net #Description: The test script #Copyright (C): 2021 All rights reserved #********************************************************************************************* func1 func1(){ echo func1 is runing } [root@rocky8 ~]# bash test1.sh test1.sh: line 12: func1: command not found #函数要先定义,再执行 [root@rocky8 ~]# vim test1.sh #!/bin/bash # #********************************************************************************************** #Author: Raymond #QQ: 88563128 #Date: 2021-10-21 #FileName: test1.sh #URL: raymond.blog.csdn.net #Description: The test script #Copyright (C): 2021 All rights reserved #********************************************************************************************* func1 func1(){ echo func1 is runing } func1 [root@rocky8 ~]# bash test1.sh test1.sh: line 12: func1: command not found func1 is runing
可以将经常使用的函数存入一个单独的函数文件,然后将函数文件载入shell,再进行调用函数
文件名可任意选取,但最好与相关任务有某种联系,例如:functions
一旦函数文件载入shell,就可以在命令行或脚本中调用函数。可以使用delcare -f 或set 命令查看所有定义的函数,其输出列表包括已经载入shell的所有函数
若要改动函数,首先用unset命令从shell中删除函数。改动完毕后,再重新载入此文件
实现函数文件的过程:
. filename 或 source filename
范例:
[root@rocky8 ~]# vim test2.sh #!/bin/bash # #********************************************************************************************** #Author: Raymond #QQ: 88563128 #Date: 2021-10-21 #FileName: test2.sh #URL: raymond.blog.csdn.net #Description: The test script #Copyright (C): 2021 All rights reserved #********************************************************************************************* func1(){ echo func1 is runing } func1 [root@rocky8 ~]# bash test2.sh func1 is runing [root@rocky8 ~]# vim functions func1 (){ echo func1 is running } func2 (){ echo func2 is running } [root@rocky8 ~]# vim test1.sh #!/bin/bash # #********************************************************************************************** #Author: Raymond #QQ: 88563128 #Date: 2021-10-21 #FileName: test1.sh #URL: raymond.blog.csdn.net #Description: The test script #Copyright (C): 2021 All rights reserved #********************************************************************************************* . functions declare -F func1 [root@rocky8 ~]# bash test1.sh declare -f func1 declare -f func2 func1 is running [root@rocky8 ~]# exit logout [root@rocky8 ~]# declare -F declare -f gawklibpath_append declare -f gawklibpath_default declare -f gawklibpath_prepend declare -f gawkpath_append declare -f gawkpath_default declare -f gawkpath_prepend
变量作用域:
注意:
在函数中定义本地变量的方法
local NAME=VALUE
范例:
[root@rocky8 ~]# vim functions func1 (){ name=raymond echo func1 is running echo "func1:name=$name" } func2 (){ echo func2 is running } [root@rocky8 ~]# vim test1.sh #!/bin/bash # #********************************************************************************************** #Author: Raymond #QQ: 88563128 #Date: 2021-10-21 #FileName: test1.sh #URL: raymond.blog.csdn.net #Description: The test script #Copyright (C): 2021 All rights reserved #********************************************************************************************* . functions declare -F func1 echo $name [root@rocky8 ~]# bash test1.sh declare -f func1 declare -f func2 func1 is running func1:name=raymond raymond [root@rocky8 ~]# vim test1.sh #!/bin/bash # #********************************************************************************************** #Author: Raymond #QQ: 88563128 #Date: 2021-10-21 #FileName: test1.sh #URL: raymond.blog.csdn.net #Description: The test script #Copyright (C): 2021 All rights reserved #********************************************************************************************* . functions declare -F name=tom func1 echo $name [root@rocky8 ~]# bash test1.sh declare -f func1 declare -f func2 func1 is running func1:name=raymond raymond [root@rocky8 ~]# bash -x test1.sh + . functions + declare -F declare -f func1 declare -f func2 + name=tom + func1 + name=raymond + echo func1 is running func1 is running + echo func1:name=raymond func1:name=raymond + echo raymond raymond [root@rocky8 ~]# vim test1.sh #!/bin/bash # #********************************************************************************************** #Author: Raymond #QQ: 88563128 #Date: 2021-10-21 #FileName: test1.sh #URL: raymond.blog.csdn.net #Description: The test script #Copyright (C): 2021 All rights reserved #********************************************************************************************* . functions declare -F func1 name=tom echo $name [root@rocky8 ~]# bash test1.sh declare -f func1 declare -f func2 func1 is running func1:name=raymond tom [root@rocky8 ~]# vim functions func1 (){ local name=raymond echo func1 is running echo "func1:name=$name" } func2 (){ echo func2 is running } #local 定义的变量只能在函数体内工作 [root@rocky8 ~]# vim test1.sh #!/bin/bash # #********************************************************************************************** #Author: Raymond #QQ: 88563128 #Date: 2021-10-21 #FileName: test1.sh #URL: raymond.blog.csdn.net #Description: The test script #Copyright (C): 2021 All rights reserved #********************************************************************************************* . functions declare -F name=tom func1 echo $name [root@rocky8 ~]# bash test1.sh declare -f func1 declare -f func2 func1 is running func1:name=raymond tom [root@rocky8 ~]# vim test1.sh #!/bin/bash # #********************************************************************************************** #Author: Raymond #QQ: 88563128 #Date: 2021-10-21 #FileName: test1.sh #URL: raymond.blog.csdn.net #Description: The test script #Copyright (C): 2021 All rights reserved #********************************************************************************************* . functions declare -F name=tom echo $name func1 echo $name [root@rocky8 ~]# bash test1.sh declare -f func1 declare -f func2 tom func1 is running func1:name=raymond tom [root@rocky8 ~]# vim test1.sh #!/bin/bash # #********************************************************************************************** #Author: Raymond #QQ: 88563128 #Date: 2021-10-21 #FileName: test1.sh #URL: raymond.blog.csdn.net #Description: The test script #Copyright (C): 2021 All rights reserved #********************************************************************************************* . functions declare -F name=raymond echo before function:name=$name func1 echo agter function:name=$name [root@rocky8 ~]# bash test1.sh declare -f func1 declare -f func2 before function:name=raymond func1 is running func1:name=raymond agter function:name=raymond
函数的执行结果返回值:
函数的退出状态码:
return 从函数中返回,用最后状态命令决定返回值
return 0 无错误返回
return 1-255 有错误返回
范例:
[root@rocky8 ~]# type return return is a shell builtin [root@rocky8 ~]# help return return: return [n] Return from a shell function. Causes a function or sourced script to exit with the return value specified by N. If N is omitted, the return status is that of the last command executed within the function or script. Exit Status: Returns N, or failure if the shell is not executing a function or script. [root@rocky8 ~]# return 10 -bash: return: can only `return' from a function or sourced script [root@rocky8 ~]# vim test2.sh #!/bin/bash # #********************************************************************************************** #Author: Raymond #QQ: 88563128 #Date: 2021-10-21 #FileName: test2.sh #URL: raymond.blog.csdn.net #Description: The test script #Copyright (C): 2021 All rights reserved #********************************************************************************************* . functions func2 echo $? [root@rocky8 ~]# bash test2.sh func2 is running 0 [root@rocky8 ~]# vim functions func1 (){ local name=raymond echo func1 is running echo "func1:name=$name" } func2 (){ echo func2 is running exit 123 } [root@rocky8 ~]# bash test2.sh func2 is running [root@rocky8 ~]# bash -x test2.sh + . functions + func2 + echo func2 is running func2 is running + exit 123 [root@rocky8 ~]# vim functions func1 (){ local name=raymond echo func1 is running echo "func1:name=$name" } func2 (){ echo func2 is running return 123 } [root@rocky8 ~]# bash test2.sh func2 is running 123
函数可以接受参数:
传递参数给函数:在函数名后面以空白分隔给定参数列表即可,如:testfunc arg1 arg2 …
在函数体中当中,可使用$1, 2 , . . . 调 用 这 些 参 数 ; 还 可 以 使 用 2, ...调用这些参数;还可以使用 2,...调用这些参数;还可以使用@, $*, $#等特殊变量
范例:
[root@rocky8 ~]# vim test3.sh #!/bin/bash # #********************************************************************************************** #Author: Raymond #QQ: 88563128 #Date: 2021-10-21 #FileName: test3.sh #URL: raymond.blog.csdn.net #Description: The test script #Copyright (C): 2021 All rights reserved #********************************************************************************************* . functions add 2 3 [root@rocky8 ~]# vim functions func1 (){ local name=raymond echo func1 is running echo "func1:name=$name" } func2 (){ echo func2 is running return 123 } add(){ local i=$1 local j=$2 echo $[i+j] } [root@rocky8 ~]# bash test3.sh 5 [root@rocky8 ~]# vim test3.sh #!/bin/bash # #********************************************************************************************** #Author: Raymond #QQ: 88563128 #Date: 2021-10-21 #FileName: test3.sh #URL: raymond.blog.csdn.net #Description: The test script #Copyright (C): 2021 All rights reserved #********************************************************************************************* . functions add $1 $2 [root@rocky8 ~]# bash test3.sh 5 6 11 [root@rocky8 ~]# vim functions func1 (){ local name=raymond echo func1 is running echo "func1:name=$name" } func2 (){ echo func2 is running return 123 } add(){ local i=$1 local j=$2 echo $[i+j] } sub(){ local i=$1 local j=$2 echo $[i-j] } [root@rocky8 ~]# vim test3.sh #!/bin/bash # #********************************************************************************************** #Author: Raymond #QQ: 88563128 #Date: 2021-10-21 #FileName: test3.sh #URL: raymond.blog.csdn.net #Description: The test script #Copyright (C): 2021 All rights reserved #********************************************************************************************* . functions case $1 in add) add $2 $3 ;; sub) sub $2 $3 ;; *) echo input false ;; esac [root@rocky8 ~]# bash test3.sh 5 6 input false [root@rocky8 ~]# bash test3.sh add 5 6 11 [root@rocky8 ~]# bash test3.sh sub 7 6 1
范例:实现进度条功能
[root@rocky8 ~]# vim progress_chart.sh #!/bin/bash # #********************************************************************************************** #Author: Raymond #QQ: 88563128 #Date: 2021-10-21 #FileName: progress_chart.sh #URL: raymond.blog.csdn.net #Description: The test script #Copyright (C): 2021 All rights reserved #********************************************************************************************* function print_chars(){ # 传入的第一个参数指定要打印的字符串 local char="$1" # 传入的第二个参数指定要打印多少次指定的字符串 local number="$2" local c for ((c = 0; c < number; ++c)); do printf "$char" done } COLOR=32 declare -i end=50 for ((i = 1; i <= end; ++i)); do printf "\e[1;${COLOR}m\e[80D[" print_chars "#" $i print_chars " " $((end - i)) printf "] %3d%%\e[0m" $((i * 2)) sleep 0.1s done echo [root@rocky8 ~]# bash progress_chart.sh [##################################################] 100%
函数递归:函数直接或间接调用自身,注意递归层数,可能会陷入死循环
递归特点:
范例: 无出口的递归函数调用
[root@rocky8 ~]# func () { let i++;echo $i;echo "func is running..,"; func; } [root@rocky8 ~]# func
递归示例:
阶乘是基斯顿·卡曼于 1808 年发明的运算符号,是数学术语,一个正整数的阶乘(factorial)是所有小于及等于该数的正整数的积,并且0和1的阶乘为1,自然数n的阶乘写作n!
n!=1×2×3×…×n
阶乘亦可以递归方式定义:0!=1,n!=(n-1)!×n
n!=n(n-1)(n-2)…1
n(n-1)! = n(n-1)(n-2)!
范例:fact.sh
[root@rocky8 ~]# vim fact.sh #!/bin/bash # #********************************************************************************************** #Author: Raymond #QQ: 88563128 #Date: 2021-10-21 #FileName: fact.sh #URL: raymond.blog.csdn.net #Description: The test script #Copyright (C): 2021 All rights reserved #********************************************************************************************* fact(){ if [ $1 -eq 1 ];then echo 1 else echo $[$1*$(fact $[$1-1])] fi } fact $1 [root@rocky8 ~]# bash fact.sh 5 120 [root@rocky8 ~]# vim fact2.sh #!/bin/bash # #********************************************************************************************** #Author: Raymond #QQ: 88563128 #Date: 2021-10-21 #FileName: fact2.sh #URL: raymond.blog.csdn.net #Description: The test script #Copyright (C): 2021 All rights reserved #********************************************************************************************* fact(){ local num=$1 if [[ $num -eq 0 ]];then fac=1 else dec=$((num-1)) fact $dec fac=$((num*fac)) fi } fact $1 echo "$1的阶乘是:$fac" [root@rocky8 ~]# bash fact2.sh 5 5的阶乘是:120
fork 炸弹是一种恶意程序,它的内部是一个不断在 fork 进程的无限循环,实质是一个简单的递归程序。由于程序是递归的,如果没有任何限制,这会导致这个简单的程序迅速耗尽系统里面的所有资源
参考:https://en.wikipedia.org/wiki/Fork_bomb
函数
:(){ :|:& };: bomb() { bomb | bomb & }; bomb
脚本实现
[root@rocky8 ~]# :(){ :|:& };: [1] 8722 [root@rocky8 ~]# vim Bomb.sh #!/bin/bash # #********************************************************************************************** #Author: Raymond #QQ: 88563128 #Date: 2021-10-21 #FileName: Bomb.sh #URL: raymond.blog.csdn.net #Description: The test script #Copyright (C): 2021 All rights reserved #********************************************************************************************* ./$0|./$0&