高级Bash脚本编程指南
dgkgnrt
|
11#
dgkgnrt 发表于 2006-05-25 09:30
Example 9-3 再来一个时间输入
################################Start Script####################################### 1 #!/bin/bash 2 # timeout.sh 3 4 # Stephane Chazelas编写, 5 #+ 本书作者进行了一些修改. 6 7 INTERVAL=5 # timeout间隔 8 9 timedout_read() { 10 timeout=$1 11 varname=$2 12 old_tty_settings=`stty -g` 13 stty -icanon min 0 time ${timeout}0 14 eval read $varname # 或者就是 read $varname 15 stty "$old_tty_settings" 16 # 察看"stty"的man页. 17 } 18 19 echo; echo -n "What's your name? Quick! " 20 timedout_read $INTERVAL your_name 21 22 # 这种方法可能不是每个终端类型都可以正常使用的. 23 # 最大的timeout依赖于具体的终端. 24 #+ (一般都是25.5秒). 25 26 echo 27 28 if [ ! -z "$your_name" ] # If name input before timeout... 29 then 30 echo "Your name is $your_name." 31 else 32 echo "Timed out." 33 fi 34 35 echo 36 37 # 这个脚本的行为可能与"timed-input.sh"有点不同. 38 # 在每次按键的时候,计数器都会重置. 39 40 exit 0 ################################End Script######################################### 或许,最简单的办法就是使用-t选项来read了. Example 9-4 Timed read ################################Start Script####################################### 1 #!/bin/bash 2 # t-out.sh 3 # "syngin seven"的一个很好的提议 (thanks). 4 5 6 TIMELIMIT=4 # 4 seconds 7 8 read -t $TIMELIMIT variable <&1 9 # ^^^ 10 # 在这个例子中,对于Bash 1.x和2.x就需要使用"<&1" 11 # 但对于Bash 3.x就不需要. 12 13 echo 14 15 if [ -z "$variable" ] # Is null? 16 then 17 echo "Timed out, variable still unset." 18 else 19 echo "variable = $variable" 20 fi 21 22 exit 0 ################################End Script######################################### $UID 用户ID号. 当前用户的id号,在/etc/passwd中记录. 这个值不会因为用户使用了su命令而改变.$UID是只读变量,不容易在命令行或者是脚 本中被修改,并且和内建的id命令很相像. Example 9-5 我是root? ################################Start Script####################################### 1 #!/bin/bash 2 # am-i-root.sh: 我是不是root用户? 3 4 ROOT_UID=0 # Root的$UID是0. 5 6 if [ "$UID" -eq "$ROOT_UID" ] # 是否是root用户,请站出来. 7 then 8 echo "You are root." 9 else 10 echo "You are just an ordinary user (but mom loves you just the same)." 11 fi 12 13 exit 0 14 15 16 # ============================================================= # 17 # 下边的代码将不被执行,因为脚本已经退出了. 18 19 # 检验是root用户的一种可选方法: 20 21 ROOTUSER_NAME=root 22 23 username=`id -nu` # Or... username=`whoami` 24 if [ "$username" = "$ROOTUSER_NAME" ] 25 then 26 echo "Rooty, toot, toot. You are root." 27 else 28 echo "You are just a regular fella." 29 fi ################################End Script######################################### 见例子Example 2-3 注意:变量$ENV,$LOGNAME,$MAIL,$TERM,$USER,和$USERNAME并不是Bash的内建变量.它 们经常被设置成环境变量,它们一般都放在Bash的安装文件中.$SHELL,用户登录的 shell的名字,可能是从/etc/passwd设置的,也可能是在一个"init"脚本中设置的,同样 的,它也不是Bash的内建变量. tcsh% echo $LOGNAME bozo tcsh% echo $SHELL /bin/tcsh tcsh% echo $TERM rxvt bash$ echo $LOGNAME bozo bash$ echo $SHELL /bin/tcsh bash$ echo $TERM rxvt 位置参数 $0, $1, $2,等等... 位置参数,从命令行传递给脚本,或者是传递给函数.或者赋职给一个变量. (具体见Example 4-5和Example 11-15) $# 命令行或者是位置参数的个数.(见Example 33-2) $* 所有的位置参数,被作为一个单词. 注意:"$*"必须被""引用. $@ 与$*同义,但是每个参数都是一个独立的""引用字串,这就意味着参数被完整地传递, 并没有被解释和扩展.这也意味着,每个参数列表中的每个参数都被当成一个独立的 单词. 注意:"$@"必须被引用. Example 9-6 arglist:通过$*和$@列出所有的参数 ################################Start Script####################################### 1 #!/bin/bash 2 # arglist.sh 3 # 多使用几个参数来调用这个脚本,比如"one tow three". 4 5 E_BADARGS=65 6 7 if [ ! -n "$1" ] 8 then 9 echo "Usage: `basename $0` argument1 argument2 etc." 10 exit $E_BADARGS 11 fi 12 13 echo 14 15 index=1 # 初始化数量. 16 17 echo "Listing args with \"\$*\":" 18 for arg in "$*" # 如果"$*"不被""引用,那么将不能正常地工作 19 do 20 echo "Arg #$index = $arg" 21 let "index+=1" 22 done # $* sees all arguments as single word. 22 done # $* 认为所有的参数为一个单词 23 echo "Entire arg list seen as single word." 24 25 echo 26 27 index=1 # 重置数量. 28 # 如果你忘了这句会发生什么? 29 30 echo "Listing args with \"\$@\":" 31 for arg in "$@" 32 do 33 echo "Arg #$index = $arg" 34 let "index+=1" 35 done # $@ 认为每个参数都一个单独的单词. 36 echo "Arg list seen as separate words." 37 38 echo 39 40 index=1 # 重置数量. 41 42 echo "Listing args with \$* (unquoted):" 43 for arg in $* 44 do 45 echo "Arg #$index = $arg" 46 let "index+=1" 47 done # 未""引用的$*把参数作为独立的单词. 48 echo "Arg list seen as separate words." 49 50 exit 0 ################################End Script######################################### 在shift命令后边,$@将保存命令行中剩余的参数,而$1被丢掉了. 1 #!/bin/bash 2 # 使用 ./scriptname 1 2 3 4 5 来调用这个脚本 3 4 echo "$@" # 1 2 3 4 5 5 shift 6 echo "$@" # 2 3 4 5 7 shift 8 echo "$@" # 3 4 5 9 10 # 每个"shift"都丢弃$1. 11 # "$@" 将包含剩下的参数. $@也作为为工具使用,用来过滤传给脚本的输入. cat "$@"结构接受从stdin传来的输入,也接受从参数中指定的文件传来的输入. 具体见Example 12-21和Example 12-22. 注意*和$@的参数有时会不一致,发生令人迷惑的行为,这依赖于$IFS的设置. Example 9-7 不一致的$*和$@行为 ################################Start Script#######################################
复制内容到剪贴板
################################End Script#########################################代码:1 #!/bin/bash2 3 # "$*"和"$@"的古怪行为, 4 #+ 依赖于它们是否被""引用. 5 # 单词拆分和换行的不一致处理. 6 7 8 set -- "First one" "second" "third:one" "" "Fifth: :one" 9 # 设置这个脚本参数,$1,$2,等等. 10 11 echo 12 13 echo 'IFS unchanged, using "$*"' 14 c=0 15 for i in "$*" # 引用 16 do echo "$((c+=1)): [$i]" # 这行在下边的每个例子中都一样. 17 # Echo参数. 18 done 19 echo --- 20 21 echo 'IFS unchanged, using $*' 22 c=0 23 for i in $* # 未引用 24 do echo "$((c+=1)): [$i]" 25 done 26 echo --- 27 28 echo 'IFS unchanged, using "$@"' 29 c=0 30 for i in "$@" 31 do echo "$((c+=1)): [$i]" 32 done 33 echo --- 34 35 echo 'IFS unchanged, using $@' 36 c=0 37 for i in $@ 38 do echo "$((c+=1)): [$i]" 39 done 40 echo --- 41 42 IFS=: 43 echo 'IFS=":", using "$*"' 44 c=0 45 for i in "$*" 46 do echo "$((c+=1)): [$i]" 47 done 48 echo --- 49 50 echo 'IFS=":", using $*' 51 c=0 52 for i in $* 53 do echo "$((c+=1)): [$i]" 54 done 55 echo --- 56 57 var=$* 58 echo 'IFS=":", using "$var" (var=$*)' 59 c=0 60 for i in "$var" 61 do echo "$((c+=1)): [$i]" 62 done 63 echo --- 64 65 echo 'IFS=":", using $var (var=$*)' 66 c=0 67 for i in $var 68 do echo "$((c+=1)): [$i]" 69 done 70 echo --- 71 72 var="$*" 73 echo 'IFS=":", using $var (var="$*")' 74 c=0 75 for i in $var 76 do echo "$((c+=1)): [$i]" 77 done 78 echo --- 79 80 echo 'IFS=":", using "$var" (var="$*")' 81 c=0 82 for i in "$var" 83 do echo "$((c+=1)): [$i]" 84 done 85 echo --- 86 87 echo 'IFS=":", using "$@"' 88 c=0 89 for i in "$@" 90 do echo "$((c+=1)): [$i]" 91 done 92 echo --- 93 94 echo 'IFS=":", using $@' 95 c=0 96 for i in $@ 97 do echo "$((c+=1)): [$i]" 98 done 99 echo --- 100 101 var=$@ 102 echo 'IFS=":", using $var (var=$@)' 103 c=0 104 for i in $var 105 do echo "$((c+=1)): [$i]" 106 done 107 echo --- 108 109 echo 'IFS=":", using "$var" (var=$@)' 110 c=0 111 for i in "$var" 112 do echo "$((c+=1)): [$i]" 113 done 114 echo --- 115 116 var="$@" 117 echo 'IFS=":", using "$var" (var="$@")' 118 c=0 119 for i in "$var" 120 do echo "$((c+=1)): [$i]" 121 done 122 echo --- 123 124 echo 'IFS=":", using $var (var="$@")' 125 c=0 126 for i in $var 127 do echo "$((c+=1)): [$i]" 128 done 129 130 echo 131 132 # 用ksh或者zsh -y来试试这个脚本. 133 134 exit 0 135 136 # This example script by Stephane Chazelas, 137 # and slightly modified by the document author. 注意@和$*中的参数只有在""中才会不同. Example 9-8 当$IFS为空时的$*和$@ ################################Start Script####################################### 1 #!/bin/bash 2 3 # 如果$IFS被设置为空时, 4 #+ 那么"$*" 和"$@" 将不会象期望那样echo出位置参数. 5 6 mecho () # Echo 位置参数. 7 { 8 echo "$1,$2,$3"; 9 } 10 11 12 IFS="" # 设置为空. 13 set a b c # 位置参数. 14 15 mecho "$*" # abc,, 16 mecho $* # a,b,c 17 18 mecho $@ # a,b,c 19 mecho "$@" # a,b,c 20 21 # 当$IFS设置为空时,$* 和$@ 的行为依赖于 22 #+ 正在运行的Bash或者sh的版本. 23 # 所以在脚本中使用这种"feature"不是明智的行为. 24 25 26 # Thanks, Stephane Chazelas. 27 28 exit 0 ################################End Script######################################### 其他的特殊参数 $- 传递给脚本的falg(使用set命令).参考Example 11-15. 注意:这起初是ksh的特征,后来被引进到Bash中,但不幸的是,在Bash中它看上去也不 能可靠的工作.使用它的一个可能的方法就是让这个脚本进行自我测试(查看是否是交 互的). $! 在后台运行的最后的工作的PID(进程ID). 1 LOG=$0.log 2 3 COMMAND1="sleep 100" 4 5 echo "Logging PIDs background commands for script: $0" >> "$LOG" 6 # 所以它们可以被监控,并且在必要的时候kill掉. 7 echo >> "$LOG" 8 9 # Logging 命令. 10 11 echo -n "ID of \"$COMMAND1\": " >> "$LOG" 12 ${COMMAND1} & 13 echo $! >> "$LOG" 14 # PID of "sleep 100": 1506 15 16 # Thank you, Jacques Lederer, for suggesting this. 1 possibly_hanging_job & { sleep ${TIMEOUT}; eval 'kill -9 $!' &> /dev/null; } 2 # 强制结束一个品行不良的程序. 3 # 很有用,比如在init脚本中. 4 5 # Thank you,Sylvain Fourmanoit,for this creative use of the "!" variable. $_ 保存之前执行的命令的最后一个参数. Example 9-9 下划线变量 ################################Start Script####################################### 1 #!/bin/bash 2 3 echo $_ # /bin/bash 4 # 只是调用/bin/bash来运行这个脚本. 5 6 du >/dev/null # 将没有命令的输出 7 echo $_ # du 8 9 ls -al >/dev/null # 没有命令输出 10 echo $_ # -al (最后的参数) 11 12 : 13 echo $_ # : ################################End Script######################################### |