例子 9-5. 我是root吗?
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` # 或者... 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
--------------------------------------------------------------------------------
也参考一下例子 2-3.
变量$ENV, $LOGNAME, $MAIL, $TERM, $USER, 和$USERNAME$ENV,都不是Bash内建的。然而常常在Bash的启动文件之一里作为环境变量设置。$SHELL变量是用户的登录shell的名字,它可以在/etc/passwd文件里设置或是在一个“初始化”的脚本里设置,并且它同样不是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,等等
位置参数由命令行传给脚本或传给一个函数,或设置(set)给一个变量(参考例子 4-5和例子 11-15)
$# 命令行参数[2]或者是位置参数的数量(参考例子 33-2)
$* 所有的位置参数都被当成单个单元。
"$*"必须被引号引起来。
$@ 和$*相同,但每个参数都是一个引起的字符串。那是说,参数都是没有被解析或扩展,是完整无缺地被传递的。这是说在参数列表中的每一个参数都被看作是一个单独的单元。
当然,"$@"应该被引号引起来。
--------------------------------------------------------------------------------
例子 9-6. arglist: 用$*和$@列出参数来
1 #!/bin/bash 2 # arglist.sh 3 # 用几个参数来运行这个脚本,比如说"one two 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. 23 echo "Entire arg list seen as single word." 24 25 echo 26 27 index=1 # Reset count. 28 # What happens if you forget to do this? 29 30 echo "Listing args with \"\$@\":" 31 for arg in "$@" 32 do 33 echo "Arg #$index = $arg" 34 let "index+=1" 35 done # $@ sees arguments as separate words. 36 echo "Arg list seen as separate words." 37 38 echo 39 40 index=1 # Reset count. 41 42 echo "Listing args with \$* (unquoted):" 43 for arg in $* 44 do 45 echo "Arg #$index = $arg" 46 let "index+=1" 47 done # Unquoted $* sees arguments as separate words. 48 echo "Arg list seen as separate words." 49 50 exit 0
--------------------------------------------------------------------------------
在一个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 # 然后"$@"保存剩下的参数。
The $@ special parameter finds use as a tool for filtering input into shell scripts. The cat "$@" construction accepts input to a script either from stdin or from files given as parameters to the script. See Example 12-21 and Example 12-22.
依赖于$IFS变量的设置,$*和$@变量有时会表现不一致的令人迷惑的行为。
--------------------------------------------------------------------------------
例子 9-7. $*和$@的不一致
1 #!/bin/bash 2 3 # Erratic behavior of the "$*" and "$@" internal Bash variables, 4 #+ depending on whether they are quoted or not. 5 # Inconsistent handling of word splitting and linefeeds. 6 7 8 set -- "First one" "second" "third:one" "" "Fifth: :one" 9 # Setting the script arguments, $1, $2, etc. 10 11 echo 12 13 echo 'IFS unchanged, using "$*"' 14 c=0 15 for i in "$*" # quoted 16 do echo "$((c+=1)): [$i]" # This line remains the same in every instance. 17 # Echo args. 18 done 19 echo --- 20 21 echo 'IFS unchanged, using $*' 22 c=0 23 for i in $* # unquoted 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 # Try this script with ksh or zsh -y. 133 134 exit 0 135 136 # 这个脚本由Stephane Chazelas所写, 137 # 并由本书作者做了少些修改.
--------------------------------------------------------------------------------
$@和$*仅仅在被双引号引住时不同。
--------------------------------------------------------------------------------
例子 9-8. 当$IFS为空时的$*和$@
1 #!/bin/bash 2 3 # 如果$IFS被设置,但值是空的, 4 #+ 则"$*"和"$@"不会像希望的那样显示位置参数。 5 6 mecho () # 显示位置参数. 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 # 因此在一个脚本里使用这种“特性”是失策的。 24 25 26 # 多谢Stephane Chazelas. 27 28 exit 0
--------------------------------------------------------------------------------
其它的特殊参数
$- (使用set命令)传给脚本的标记. 参考例子 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 # So they can be monitored, and killed as necessary. 7 echo >> "$LOG" 8 9 # Logging commands. 10 11 echo -n "PID of \"$COMMAND1\": " >> "$LOG" 12 ${COMMAND1} & 13 echo $! >> "$LOG" 14 # PID of "sleep 100": 1506 15 16 # 多谢Jacques Lederer的建议.
1 possibly_hanging_job & { sleep ${TIMEOUT}; eval 'kill -9 $!' &> /dev/null; } 2 # 强迫一个出错的程序结束退出. 3 # 这很有用,尤其在初始化脚本中. 4 5 # 多谢Sylvain Fourmanoit发现"!"变量创造性的用处.
$_ 保存前一个命令最后一个参数的变量值。
--------------------------------------------------------------------------------
例子 9-9. 下划线变量
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 $_ # :
--------------------------------------------------------------------------------
$? 一个命令,函数或脚本自身的退出状态码(参考例子 23-7)
$$ 脚本本身的进程PID。$$变量常被用于脚本中生成一个"唯一的"临时文件名(参考例子 A-13, 例子 29-6, 例子 12-28, 和例子 11-25). 这通常比调用mktemp还要简单。
注 [1] 当然,当前运行的脚本的PID就是$$。 [2] 术语"argument"和"parameter"常常可互相替换。在这个文档的上下文中,它们有相同的意思,即它们是传递给脚本或函数的变量。[译者注:翻译时,译者已经把这两个术语依据上下文意思都做了适当的翻译]. |