Bash不但支持函数编程,还支持递归调用;可以通过命令行向脚本传递参数
本文主要谈谈脚本编程的函数思想
/*可以直接写函数名加圆括号*/
func(){
...
cmd
...
[return value] /*返回值是可选的*/
}
/*也可以在函数名前加上function关键字*/
function func(){
...
cmd
...
[return value] /*返回值是可选的*/
函数调用
func /*直接用函数名调用(不加括号),切必须写在函数定义的后面*/
普通参数
可以通过命令行把参数传递个脚本程序或者其子程序(函数)
#!/bin/bash
#Filename: script.sh
func(){
echo "$1"
}
func $1
---------------------
~> ./script.sh hello world
~> hello
特殊参数
$0
:文件名
$1 $2 $3
:传入的第1、2、3个命令行参数(以此类推)
$#
:传入的命令行参数长度
$*
:用于指代传入的每一个参数
$@
:类似上一条指令,该标识把传入的所有参数视为一个整体
$?
:给出上一条命令的状态返回值(正常退出时为0)
和一般的编程语言一样,脚本编程也支持递归
F(){echo $1 F hello} /*该函数将不断打印“hello”*/
/*Fork炸弹*/
/*递归函数,不断生成新的进程,最终造成拒绝服务攻击*/
/*可以通过修改配置文件/etc/security/limits.conf来限制可生成的最大进程数来避开Fork炸弹攻击*/
---------------------------------------------------
:(){:|:& };:
---------------------------------------------------
其中,
:()定义新函数,函数名为:
:|:递归调用+管道命令,将前一个函数的输出引到另一次调用该函数;总的作用是每次调用函数:时会分成两份拷贝
&调用间脱钩,即函数调用前的&将子进程放入后台时,使得函数被杀死后为其所调用的两个:函数还能继续执行
;函数定义结束后立即进行下一步操作
:引爆fork炸弹
---------------------------------------------------
fork炸弹只是一种递归调用的思想,在具体语言中形式变化多样
---------------------------------------------------
/*Perl版本的fork炸弹*/
fork while fork
函数也能像环境变量一样用export命令导出;这样一来函数的作用域就可以扩展到子进程中
export -f fname
read var /*直到按下回车键从缓冲区读取数据到var*/
read -n 2 var /*读取两个字符并保存在var中*/
read -s var /*无回显读取密码*/
read -p "Enter..." var /*显示提示信息*/
read -t 5 var /*在5秒内从终端读取数据*/
read -d ":" var /*以:界定符作为输入行的结束*/
内部字段分隔符(IFS)是shell脚本编程的一个重要概念,用来把命令行分隔成字段;IFS是存储界定符的一个环境变量
IFS可以是空白符、制表符、回车符中的一个或几个;默认情况下IFS为空白符
/*IFS实战:迭代输出*/
data="name,sex,rollno,location"
IFS=, #将IFS从空白符换成逗号
for item in $data;
do
echo Item: $item
done
/*
* Item: name
* Item: sex
* Item: rollno
* Item: location
*/
循环
/*for循环,list可以是一个字符串或其它序列*/
for var in list;
do
cmd; #使用变量$var
done
# list={1..50}, list="hi,world"
------------------------------------------------
/*for循环也可以使用C语言的风格*/
for((i=0;i<10;i++))
{
cmd;
}
/*while循环,使用true作为条件将产生无限循环*/
while condition
do
cmd;
done
/*until循环*/
# e.g.
x=0;
until [$x -eq 9];
do
let x++; echo $x;
done
比较测试
/*if条件*/
if condition;
then
cmds;
fi
/*else if*/
if condition1;
then;
cmds;
else if condition2; then
cmds;
else
cmds;
fi
if-else语句可以进行嵌套,if的判断语句可能会变得很长,这时候可以用逻辑运算符使其变得尽量简洁
[condition] && action 若条件为真则执行
[condition] || action 若条件为假则执行
算数比较运算符
-gt:大于
-lt:小于
-ge:大于等于
-le:小于等于
逻辑操作符
-a:逻辑与
-o:逻辑或
!:逻辑非
切记切记!在condition和两边的’[’ ‘]’之间一定要有一个空格(否则报错!)
文件系统的相关测试和字符串的相关测试和数字略有不同:
/*文件系统的*/
-f:若给定的变量包含正常的文件路径或文件名,则返回真
-x:若给定的变量包含的文件可执行,则返回真
-d:若给定的变量包含的是目录,则返回真
-e:若给定的变量包含的文件存在,则返回真
-c:若给定的变量包含的是一个字符设备文件的路径,则返回真
-b:若给定的变量包含的是一个块设备文件的路径,则返回真
-w:若给定的变量包含的文件可写,则返回真
-r:若给定的变量包含的文件可读,则返回真
-L:若给定的变量包含的文件包含的是一个符号链接,则返回真
/*字符串比较*/
= 判断两个字符串是否内容相同
== 这是检查字符串是否相等的另一种写法(和写法一等价)
!= 判断两个字符串是否不等
-z 非字符串
-n:非空字符串 //说明,-z和-n都写在字符串变量之前如 [[ -n $str ]]
注意!在判断字符串相等的等号“=”和变量之间有一个空格!千万不要漏写,否则就不是判断相等,而成了赋值的意思!
另外,判断测试字符串时最好用两个方括号!因为有时候用单个方括号可能会引起错误!