33.4. 递归
优质
小牛编辑
138浏览
2023-12-01
脚本是否能 递归地调用自己本身? 当然可以.
例子 33-8. 递归调用自己本身的(无用)脚本
1 #!/bin/bash 2 # recurse.sh 3 4 # 脚本能否递归地调用自己? 5 # 是的, 但这有什么实际的用处吗? 6 # (看下面的.) 7 8 RANGE=10 9 MAXVAL=9 10 11 i=$RANDOM 12 let "i %= $RANGE" # 产生一个从 0 到 $RANGE - 1 之间的随机数. 13 14 if [ "$i" -lt "$MAXVAL" ] 15 then 16 echo "i = $i" 17 ./$0 # 脚本递归地调用再生成一个和自己一样的实例. 18 fi # 每个子脚本做的事都一样, 19 #+ 直到产生的变量 $i 和变量 $MAXVAL 相等. 20 21 # 用"while"循环代替"if/then"测试会引起错误. 22 # 解释为什么会这样. 23 24 exit 0 25 26 # 注: 27 # ---- 28 # 脚本要正确地工作必须有执行权限. 29 # 这是指用"sh"命令来调用这个脚本而没有设置正确权限导致的问题. 30 # 请解释原因.
例子 33-9. 递归调用自己本身的(有用)脚本
1 #!/bin/bash 2 # pb.sh: 电话本(phone book) 3 4 # 由Rick Boivie编写,已得到使用许可. 5 # 由ABS文档作者修改. 6 7 MINARGS=1 # 脚本需要至少一个参数. 8 DATAFILE=./phonebook 9 # 在当前目录下名为"phonebook"的数据文件必须存在 10 # 11 PROGNAME=$0 12 E_NOARGS=70 # 没有参数的错误值. 13 14 if [ $# -lt $MINARGS ]; then 15 echo "Usage: "$PROGNAME" data" 16 exit $E_NOARGS 17 fi 18 19 20 if [ $# -eq $MINARGS ]; then 21 grep $1 "$DATAFILE" 22 # 如果$DATAFILE文件不存在,'grep' 会打印一个错误信息. 23 else 24 ( shift; "$PROGNAME" $* ) | grep $1 25 # 脚本递归调用本身. 26 fi 27 28 exit 0 # 脚本在这儿退出. 29 # 因此Therefore, 从这行开始可以写没有#开头的的注释行 30 # 31 32 # ------------------------------------------------------------------------ 33 "phonebook"文件的例子: 34 35 John Doe 1555 Main St., Baltimore, MD 21228 (410) 222-3333 36 Mary Moe 9899 Jones Blvd., Warren, NH 03787 (603) 898-3232 37 Richard Roe 856 E. 7th St., New York, NY 10009 (212) 333-4567 38 Sam Roe 956 E. 8th St., New York, NY 10009 (212) 444-5678 39 Zoe Zenobia 4481 N. Baker St., San Francisco, SF 94338 (415) 501-1631 40 # ------------------------------------------------------------------------ 41 42 $bash pb.sh Roe 43 Richard Roe 856 E. 7th St., New York, NY 10009 (212) 333-4567 44 Sam Roe 956 E. 8th St., New York, NY 10009 (212) 444-5678 45 46 $bash pb.sh Roe Sam 47 Sam Roe 956 E. 8th St., New York, NY 10009 (212) 444-5678 48 49 # 当超过一个参数传给这个脚本时, 50 #+ 它只打印包含所有参数的行.
例子 33-10. 另一个递归调用自己本身的(有用)脚本
1 #!/bin/bash 2 # usrmnt.sh, 由Anthony Richardson编写 3 # 得到允许在此使用. 4 5 # usage: usrmnt.sh 6 # 描述: 挂载设备, 调用者必须列在/etc/sudoers文件的MNTUSERS组里 7 # 8 9 # ---------------------------------------------------------- 10 # 这是一个用户挂载设备的脚本,它用sudo来调用自己. 11 # 只有拥有合适权限的用户才能用 12 13 # usermount /dev/fd0 /mnt/floppy 14 15 # 来代替 16 17 # sudo usermount /dev/fd0 /mnt/floppy 18 19 # 我使用相同的技术来处理我所有的sudo脚本, 20 #+ 因为我觉得它很方便. 21 # ---------------------------------------------------------- 22 23 # 如果 SUDO_COMMAND 变量没有设置,我们不能通过sudo来运行脚本本身. 24 #+ 传递用户的真实ID和组ID . . . 25 26 if [ -z "$SUDO_COMMAND" ] 27 then 28 mntusr=$(id -u) grpusr=$(id -g) sudo $0 $* 29 exit 0 30 fi 31 32 # 如果我们以sudo来调用运行,就会运行这儿. 33 /bin/mount $* -o uid=$mntusr,gid=$grpusr 34 35 exit 0 36 37 # 附注 (由脚本作者加注): 38 # ------------------------------------------------- 39 40 # 1) Linux允许在/etc/fstab文件中使用"users"选项 41 # 以使任何用户能挂载可移动的介质. 42 # 但是, 在一个服务器上, 43 # 我只想有限的几个用户可以存取可移动介质. 44 # 我发现使用sudo可以有更多的控制. 45 46 # 2) 我也发现sudo能通过组更方便地达成目的. 47 # 48 49 # 3) 这个方法使给予任何想给合适权限的人使用mount命令 50 # 所以要小心使用. 51 # 你也可以开发类似的脚本mntfloppy, mntcdrom,和 mntsamba来使mount命令得到更好的控制 52 # 53 # 54 #
过多层次的递归调用会耗尽脚本的堆栈空间,会引起段错误.