1、while 循环的特殊用法(遍历文件的每一行)
while read line; do
循环体
done < /PATH/FROM/SOMEFILE
依次读取/PATH/FROM/SOMEFILE 文件中的每一行,且将行赋值给变量line
练习:扫描/etc/passwd 文件每一行,如发现GECOS 字段为空,则填充用户名和单位电话为62985600 ,并提示该用户的GECOS信息修改成功。
#!/bin/bash
while read mline;do
if [ -z "`echo $mline|cut -d: -f5`" ];then
username=`echo $mline|cut -d: -f1`
chfn -f "$username" $username &>/dev/dull
chfn -p "62895000" $username &>/dev/dull
echo "finger is changed successfully"
fi
done</etc/passwd
或#while read -p “please input the number:”num;do echo the number is $num;done而且这也是个死循环
或# sum=0;while read line;do sum=$[sum+`echo $line|cut -d: -f3`];done</etc/passwd;echo $sum
2、双小括号方法,即((…)) 格式,也可以用于算术运算
双小括号方法也可以使bash Shell实现C语言风格的变量操作
例如:
#i=10
#((i++))
for循环的特殊格式:
for (( 控制变量初始化; 条件判断表达式; 控制变量的修正表达式));do
循环体
done
控制变量初始化:仅在运行到循环代码段时执行一次
控制变量的修正表达式:每轮循环结束会先进行控制变量修正运算,而后再做条件判断
例如:# sum=0;for i in {1..100};do sum=$[sum+i];done;echo $sum
#sum=0;for ((i=1;i<=100;i++)) ;do sum=$[sum+i];done;echo $sum
# for ((sum=0,i=1;i<=100;i++)) ;do sum=$[sum+i];done;echo $sum
1、 select循环与菜单
select variable in list
do
循环体命令
done
select循环主要用于创建菜单,按数字顺序排列的菜单项将显示在标准输出上,并显示PS3提示符,等待用户输入,用户输入菜单列表中的某个数字,执行相应的命令,同时用户输入的数字被保存在内置变量 REPLY中
select是个无限循环,因此要记住用 break命令退出循环,或用 exit命令终止脚本。也可以按 ctrl+c退出循
select经常和 case联合使用
与for 循环类似,可以省略 in list ,此时使用位置参量,例#select.sh gb yz hos
例如:
#!/bin/bash
select caidan in gb yz hos;do
case $caidan in
gb)
echo 10$
echo $REPLY
break
;;
yz)
echo 20$
break
;;
hos)
echo 30$
break
;;
*)
echo noexist
break
;;
esac
done
运行此脚本,其PS3提示符是#?,不过可以定义,例如在脚本中假如代码PS3=“what do you want?”
2、 函数(shell命令,shell程序,shell可以是一个终端shell、也可以是一个脚本shell)
函数function 是由若干条shell命令组成的语句块,实现代码重用和模块化编程;它与shell程序形式上是相似的,不同的是它不是一个单独的进程,不能独立运行,而是shell程序的一部分。
函数和shell程序比较相似,区别在于:
Shell程序在子Shell中运行,而Shell函数在当前Shell中运行,是shell程序的一部分,因此在当前Shell中,函数可以对shell中变量进行修改
函数由两部分组成:函数名和函数体
语法一:
function f_name {
… 函数体…
}
语法二:
f_name() {
… 函数体…
}
定义函数f2 () {
a=xixi
}
#!/bin/bash
a=haha
f2
echo $a
脚本的运行结果是输出xixi
5、函数的定义和使用:
可在交互式环境下定义函数
示例:
$dir() {
> ls -l
> }
定义该函数后,若在$后面键入dir ,即$dir其显示结果同ls -l的作用相同
该dir函数将一直保留到用户从系统退出,或执行了所示的unset 命令即$unset dir
可将函数放在脚本文件中作为它的一部分
可放在只包含函数的单独文件中
调用:函数只有被调用才会执行
调用:给定函数名,函数名出现的地方,会被自动替换为函数代码
函数的生命周期:被调用时创建,返回时终止
示例:
[root@centos7 bin]# vim functionadd-reduce.sh
#!/bin/bash
add () {
echo $[$1+$2]
}
reduce () {
echo $[$1-$2]
}
add $1 $2
reduce $1 $2
此外,函数在使用前必须定义,因此应将函数定义放在脚本开始部分,直至shell首次发现它后才能使用,调用函数仅使用其函数名即可
3、 使用函数文件
可以将经常使用的函数存入函数文件,然后将函数文件载入shell。
文件名可任意选取,但最好与相关任务有某种联系,例如:functions.main
一旦函数文件载入shell ,就可以在命令行或脚本中调用函数
可以使用set 命令显示查看所有已经载入shell 中的函数
若要改动函数,首先用unset 命令从shell中删除函数,改动完毕后,再重新载入此文件
函数文件已创建好后,要将它载入shell
定位函数文件并载入shell 的格式:
. filename 或 source filename
注意:此即< 点> < 空格> < 文件名>
这里的文件名要带正确路径(绝对或者相对路径)
示例:上例中的函数调用,可使用如下命令:
在终端shell中调用函数,如$ . functions.main
或者脚本中调用,例如在脚本中写入 . /root/funs代码,其中/root/funs是绝对路径函数文件,然后就可以使用其中的函数
函数可以接受参数:调用函数时,在函数名后面以空白分隔给定参数列表即可
例如“testfunc arg1 arg2 …”
在函数体中当中,可使用$1, $2, … 调用这些参数;还可以使用$@, $*, $# 等特殊变量
#!/bin/bash
. /root/funs
add $1 $2
reduce $1 $2
6、变量作用域:
环境变量:当前shell和子shell有效
本地变量:只在当前shell进程有效,本地变量的作用范围是当前shell脚本程序文件,包括脚本中的函数
局部变量:函数的生命周期,函数结束时变量被自动销毁
注意:如果函数中有局部变量,如果其名称同本地变量,则函数使用局部变量
在函数中定义局部变量的方法
local NAME=VALUE
7、函数的退出状态码:
(1) 默认取决于函数中执行的最后一条命令的退出状态码
(2) 自定义退出状态码, 其格式为:
return 从函数中返回,用最后执行的命令状态决定返回值
return 0 无错误返回
return 1-255 有错误
在函数中遇见return就结束函数执行,此函数中return后面的代码不再执行
使用#echo $?可以查看函数的退出状态码
8、 函数递归实例
函数递归:函数直接或间接调用自身,注意递归层数
阶乘亦可以递归方式定义:0!=1 ,n!=(n-1)! ×n
n!=n(n-1)(n-2)…1
n(n-1)! = n(n-1)(n-2)!
示例:fact.sh
#!/bin/bash
fact() {
if [ $1 -eq 0 -o $1 -eq 1 ]; then
echo 1
else
echo $[$1*$(fact $[$1-1])] 注意其中的小括号
fi
}
fact 10
另外sumR.sh
#!/bin/bash
fact() {
if [ $1 -eq 1 ]; then
echo 1
else
echo $[$1+$(fact $[$1-1])]
fi
}
fact $1
练习题
1、 每隔3秒钟到系统上获取已经登录的用户的信息;如果发现用户hacker登录,则将登录时间和主机记录于日志/var/log/login.log中,并提示该用户退出系统
#!/bin/bash
while true;do
who
who|grep -q "^shanhaibo\>"
if [ $? -eq 0 ];then
who>>/var/log/login.log
write shanhaibo <./hacker.txt
fi
sleep 3
done
2、随机生成10以内的数字,实现猜字游戏,提示比较大或小,相等则退出
#!/bin/bash
a=$[$RANDOM%11]
read -p "please input the positive integer 0-9:" b
[[ ! $b =~ [0-9] ]] && echo "this input isn't positive integer[0-9]" && exit
until [ $a -eq $b ] && echo "you are good";do
if [ $b -gt $a ];then
echo "the positive integer is bigger"
else
echo "the positive integer is less"
fi
read -p "please input the positive integer 0-9:" b
done
8、打印等腰三角形
第一种方法:
#!/bin/bash
read -p "please input the line:" n
for i in `seq 1 $n`;do
for j in `seq 1 $[n-i]`;do
echo -n " "
done
b=$[i*2-1]
for h in `seq 1 $b`;do
echo -n "#"
done
echo
done
第二种方法:
#!/bin/bash
read -p "please input the line:" n
for i in `seq 1 $n`;do
for j in `seq 1 $[n+i]`;do
if [ $j -le $[n-i] ];then
echo -n " "
elif [ $j -lt $[n+i] ];then
echo -n "#"
fi
done
echo
done
原创文章,作者:18612763863,如若转载,请注明出处:http://www.178linux.com/42378