------------------ local variables 这种变量只有在代码块或者是函数中才可见(具体见23.2和23章) environmental variables 这种变量将改变用户接口和shell的行为.
在一般的上下文中,每个进程都有自己的环境,就是一组保持进程可能引用的信息的 变量.这种情况下,shell于一个一般进程是相同的.
每次当shell启动时,它都将创建自己的环境变量.更新或者添加新的环境变量,将导致shell更新它的环境,同时也会影响所有继承自这个环境的所有子进程(由这个命令导致的).
注意:分配给环境变量的空间是受限的.创建太多的环境变量将引起空间溢出,这会引起问题. 关于eval命令,具体见第11章 bash$ eval "`seq 10000 | sed -e 's/.*/export var&=ZZZZZZZZZZZZZZ/'`" bash$ du bash: /usr/bin/du: Argument list too long
如果一个脚本设置了环境变量,需要export它,来通知本脚本的环境,这是export命令的功能,关于export命令,具体见11章. 脚本只能对它产生的子进程export变量.一个从命令行被调用的脚本export的变量,将不能影响调用这个脚本的那个命令行shell的环境.
positional parameters 就是从命令行中传进来的参数,$0, $1, $2, $3...
$0就是脚本文件的名字,$1是第一个参数,$2为第2个...,参见[1](有$0的说明),$9以后就需要打括号了,如${10},${11},${12}...两个值得注意的变量$*和$@(第9章有具体的描述),表示所有的位置参数.
Example 4-5 位置参数 ################################Start Script####################################### 1 #!/bin/bash 2 3 # 作为用例,调用这个脚本至少需要10个参数,如 4 # ./scriptname 1 2 3 4 5 6 7 8 9 10 5 MINPARAMS=10 6 7 echo 8 9 echo "The name of this script is \"$0\"." 10 # 添加./是为了当前目录 11 echo "The name of this script is \"`basename $0`\"." 12 # 去掉目录信息,具体见'basename'命令 13 14 echo 15 16 if [ -n "$1" ] # 测试变量被被引用 17 then 18 echo "Parameter #1 is $1" # "#"没被转义 19 fi 20 21 if [ -n "$2" ] 22 then 23 echo "Parameter #2 is $2" 24 fi 25 26 if [ -n "$3" ] 27 then 28 echo "Parameter #3 is $3" 29 fi 30 31 # ... 32 33 34 if [ -n "${10}" ] # 大于9的参数必须出现在{}中. 35 then 36 echo "Parameter #10 is ${10}" 37 fi 38 39 echo "-----------------------------------" 40 echo "All the command-line parameters are: "$*"" 41 42 if [ $# -lt "$MINPARAMS" ] #$#是传到脚本里的位置参数的个数 43 then 44 echo 45 echo "This script needs at least $MINPARAMS command-line arguments!" 46 fi 47 48 echo 49 50 exit 0 ################################End Script######################################### {}标记法是一种很好的使用位置参数的方法.这也需要间接引用(见Example 34-2) 1 args=$# # 位置参数的个数 2 lastarg=${!args} 3 # 或: lastarg=${!#} 4 # 注意 lastarg=${!$#} 将报错
一些脚本可能会依赖于使用不同的调用名字,而表现出不同的行为,这样一般都需要判断$0,而其他的名字都是通过ln命令产生的链接.(具体参见Example 12-2)
如果脚本需要一个命令行参数,而调用的时候,没用这个参数,这就有可能造成分配一个空变量,这样估计就会引起问题.一种解决办法就是在这个位置参数,和相关的变量后边,都添加一个额外的字符.具体见下边的例子. ################################Start Script####################################### 1 variable1_=$1_ # 而不是 variable1=$1 2 # 这将阻止一个错误,即使在调用时没使用这个位置参数. 3 4 critical_argument01=$variable1_ 5 6 # 这个扩展的字符是可以被消除掉的,就像这样. 7 variable1=${variable1_/_/} 8 # 副作用就是$variable1_多了一个下划线 9 # 这里使用了一个参数替换模版(后边会有具体的讨论) 10 # (Leaving out the replacement pattern results in a deletion.) 10 # (在一个删除动作中,节省了一个替换模式) 11 12 13 # 一个解决这种问题的更简单的做法就是,判断一下这个位置参数是否传递下来了 14 if [ -z $1 ] 15 then 16 exit $E_MISSING_POS_PARAM 17 fi 18 19 20 # 但是上边的方法将可能产生一个意外的副作用 21 # 参数替换的更好的办法应该是: 22 # ${1:-$DefaultVal} 23 # 具体察看"Parameter Substition"节 24 #+ 在第9章 ################################End Script#########################################
Example 4-6 wh,whois节点名字查询 ################################Start Script####################################### 1 #!/bin/bash 2 # ex18.sh 3 4 # Does a 'whois domain-name' lookup on any of 3 alternate servers: 5 # ripe.net, cw.net, radb.net 6 7 # 把这个脚本重命名为'wh',然后放到/usr/local/bin下 8 9 # 需要3个符号链接 10 # ln -s /usr/local/bin/wh /usr/local/bin/wh-ripe 11 # ln -s /usr/local/bin/wh /usr/local/bin/wh-cw 12 # ln -s /usr/local/bin/wh /usr/local/bin/wh-radb 13 14 E_NOARGS=65 15 16 17 if [ -z "$1" ] 18 then 19 echo "Usage: `basename $0` [domain-name]" 20 exit $E_NOARGS 21 fi 22 23 # Check script name and call proper server. 23 # 检查脚本名字,然后调用合适的服务器 24 case `basename $0` in # Or: case ${0##*/} in 25 "wh" ) whois $1@whois.ripe.net;; 26 "wh-ripe") whois $1@whois.ripe.net;; 27 "wh-radb") whois $1@whois.radb.net;; 28 "wh-cw" ) whois $1@whois.cw.net;; 29 * ) echo "Usage: `basename $0` [domain-name]";; 30 esac 31 32 exit $? ################################End Script#########################################
shift shift命令重新分配位置参数,其实就是向左移动一个位置. $1 <--- $2, $2 <--- $3, $3 <--- $4, 等等. 老的$1将消失,但是$0(脚本名)是不会改变的.如果你使用了大量的位置参数,那么 shift命令允许你存取超过10个参数.虽然{}表示法也允许这样.
Example 4-7 使用shift ################################Start Script####################################### 1 #!/bin/bash 2 # 使用'shift'来穿过所有的位置参数. 3 4 # 把这个脚本命名为shft, 5 #+ 并且使用一些参数来调用它,如: 6 # ./shft a b c def 23 skidoo 7 8 until [ -z "$1" ] # 知道所有参数都用光 9 do 10 echo -n "$1 " 11 shift 12 done 13 14 echo # 额外的换行. 15 16 exit 0 ################################End Script######################################### 在将参数传递到函数中时,shift的工作方式也基本差不多.具体见Example 33-15
注意事项: [1] 进程调用设置$0参数的脚本.一般的,这个参数就是脚本名字.具体察看execv的man页. |