shell教程

33.4. 递归

脚本是否能递归地调用自己本身?当然可以.例子33-8.递归调用自己本身的(无用)脚本#!/bin/bash#recurse.sh#脚本能否递归地调用自己?#是的,但这有什么实际的用处吗?#(看下面的.)RANGE=10MAXVAL=9i=$RANDOMlet"i%=$RANGE"#产生一个从0到$RANGE-1之间的随机数.if["$i"-lt"$MAXVAL"]thenecho"i=$i"./$

脚本是否能 递归地 调用自己本身? 当然可以.


例子 33-8. 递归调用自己本身的(无用)脚本

#!/bin/bash
# recurse.sh

#  脚本能否递归地调用自己?
#  是的, 但这有什么实际的用处吗?
#  (看下面的.)

RANGE=10
MAXVAL=9

i=$RANDOM
let "i %= $RANGE"  # 产生一个从 0 到 $RANGE - 1 之间的随机数.

if [ "$i" -lt "$MAXVAL" ]
then
  echo "i = $i"
  ./$0             #  脚本递归地调用再生成一个和自己一样的实例.
fi                 #  每个子脚本做的事都一样,
                   #+ 直到产生的变量 $i 和变量 $MAXVAL 相等.

#  用"while"循环代替"if/then"测试会引起错误.
#  解释为什么会这样.

exit 0

# 注:
# ----
# 脚本要正确地工作必须有执行权限.
# 这是指用"sh"命令来调用这个脚本而没有设置正确权限导致的问题.
# 请解释原因.


例子 33-9. 递归调用自己本身的(有用)脚本

#!/bin/bash
# pb.sh: 电话本(phone book)

# 由Rick Boivie编写,已得到使用许可.
# 由ABS文档作者修改.

MINARGS=1     #  脚本需要至少一个参数.
DATAFILE=./phonebook
              #  在当前目录下名为"phonebook"的数据文件必须存在
              #
PROGNAME=$0
E_NOARGS=70   #  没有参数的错误值.

if [ $# -lt $MINARGS ]; then
      echo "Usage: "$PROGNAME" data"
      exit $E_NOARGS
fi


if [ $# -eq $MINARGS ]; then
      grep $1 "$DATAFILE"
      #  如果$DATAFILE文件不存在,'grep' 会打印一个错误信息.
else
      ( shift; "$PROGNAME" $* ) | grep $1
      # 脚本递归调用本身.
fi

exit 0        #  脚本在这儿退出.
              #  因此Therefore, 从这行开始可以写没有#开头的的注释行
	      #

# ------------------------------------------------------------------------
"phonebook"文件的例子:

John Doe        1555 Main St., Baltimore, MD 21228          (410) 222-3333
Mary Moe        9899 Jones Blvd., Warren, NH 03787          (603) 898-3232
Richard Roe     856 E. 7th St., New York, NY 10009          (212) 333-4567
Sam Roe         956 E. 8th St., New York, NY 10009          (212) 444-5678
Zoe Zenobia     4481 N. Baker St., San Francisco, SF 94338  (415) 501-1631
# ------------------------------------------------------------------------

$bash pb.sh Roe
Richard Roe     856 E. 7th St., New York, NY 10009          (212) 333-4567
Sam Roe         956 E. 8th St., New York, NY 10009          (212) 444-5678

$bash pb.sh Roe Sam
Sam Roe         956 E. 8th St., New York, NY 10009          (212) 444-5678

#  当超过一个参数传给这个脚本时,
#+ 它只打印包含所有参数的行.


例子 33-10. 另一个递归调用自己本身的(有用)脚本

#!/bin/bash
# usrmnt.sh, 由Anthony Richardson编写
# 得到允许在此使用.

# usage:       usrmnt.sh
# 描述: 挂载设备, 调用者必须列在/etc/sudoers文件的MNTUSERS组里
#

# ----------------------------------------------------------
#  这是一个用户挂载设备的脚本,它用sudo来调用自己.
#  只有拥有合适权限的用户才能用

#   usermount /dev/fd0 /mnt/floppy

# 来代替

#   sudo usermount /dev/fd0 /mnt/floppy

#  我使用相同的技术来处理我所有的sudo脚本,
#+ 因为我觉得它很方便.
# ----------------------------------------------------------

#  如果 SUDO_COMMAND 变量没有设置,我们不能通过sudo来运行脚本本身.
#+ 传递用户的真实ID和组ID . . .

if [ -z "$SUDO_COMMAND" ]
then
   mntusr=$(id -u) grpusr=$(id -g) sudo $0 $*
   exit 0
fi

# 如果我们以sudo来调用运行,就会运行这儿.
/bin/mount $* -o uid=$mntusr,gid=$grpusr

exit 0

# 附注 (由脚本作者加注):
# -------------------------------------------------

# 1) Linux允许在/etc/fstab文件中使用"users"选项
#    以使任何用户能挂载可移动的介质.
#    但是, 在一个服务器上,
#    我只想有限的几个用户可以存取可移动介质.
#    我发现使用sudo可以有更多的控制.

# 2) 我也发现sudo能通过组更方便地达成目的.
#

# 3) 这个方法使给予任何想给合适权限的人使用mount命令
#    所以要小心使用.
#    你也可以开发类似的脚本mntfloppy, mntcdrom,和 mntsamba来使mount命令得到更好的控制
#
#
# 

过多层次的递归调用会耗尽脚本的堆栈空间,会引起段错误.

© 内存溢出 OutOfMemory.CN