shell高级编程笔记(第四章 变量和参数的介绍)

    技术2022-07-12  66

    第四章 变量和参数的介绍

    4.1 变量替换

    $ 变量替换操作符

    只有在变量被声明、赋值、unset或exported或者是在变量代表一个信号的时候,变量才会是以本来的面目出现在脚本里。变量再被赋值的时候可能需要使用=、read状态或是在循环的头部。 在""中还是会发生变量替换,这叫做部分引用或叫弱引用。而在’'中就不会发生变量替换,这叫全引用或叫全引用。具体见第五章的讨论。

    Example 4.2 变量赋值和替换

    #!/bin/bash a=375 hello=$a echo hello #hello echo $hello #375 echo ${hello} #同上 echo "$hello" #同上 echo "${hello}" #同上 echo hello="A B C D" echo $hello #A B C D echo "$hello" #A B C D echo '$hello' #$hello echo hello= echo "\$hello = " #$hello = echo var1=21 var2=22 var3=$V3 echo "var1=$var1 var2=$var2 var3=$var3" #var1=21 var2=22 var3= exit 0

    注意:一个空值变量,或者是根本就没有声明的变量,在赋值之前使用它可能会引起问题,但是还是可以用来做算术运算,它的值就好像0一样。具体参考Example 11.21

    eho "$variable" #未定义 let "variable += 5" echo "variable" #5

    4.2 变量赋值

    = 赋值操作(前后都不能有空白)

    Example 4.2 一般的变量赋值

    #!/bin/bash #赋值 a=789 echo "The value of \"a\" is $a." #使用let赋值 let a=10+5 echo "The value of \"a\" is now $a." #在for循环中 echo -n "Values of \"a\" in the loop are : " for a in 7 8 9 do echo -n "$a" done echo #在read命令状态中 echo -n "Enter \"a\"" read a echo "The value of \"a\" is now $a." exit 0

    Example 4.3 变量赋值,一般的和比较特殊的

    #!/bin/bash a=23 echo $a b=$a echo $b a=`echo Hello!` echo $a a=`ls -l` echo $a echo echo "$a" exit 0

    4.3 Bash 变量是不分类型的

    Bash并不对变量区分"类型"。本质上Bash变量都是字符串。但是依赖于上下文,Bash也允许比较操作和算术操作。决定这些的关键因素就是变量中的值是否只有数字。

    Example 4.4 整数型还是字符串型

    #!/bin/bash #int-or-string.sh:整数型还是string? a=2334 let "a += 1" echo "a = $a" #a = 2335,整数型 b=${a/23/BB} #将23替换成BB echo "b = $b" #b = BB35,将b转成了string let "b += 1" #BB35 + 1 = echo "b = $b" #b = 1 c=BB34 d=${c/BB/23} let "d += 1" echo "d = $d" #d = 2335 空变量和未声明的变量是一个整数型变量0 e="" let "e += 1" echo "e = $e" #e = 1 echo "f = $f" let "f += 1" echo "f = $f" #f = 1 exit 0

    4.4 特殊的变量类型

    local variables

    这种变量只有在代码块或者函数中才可见(具体见23.2和23章)

    environmental variables

    这种变量将改变用户接口和shell的行为

    在一般的上下文中,每个进程都有自己的环境,就是一组保持进程可能引用的信息的变量。这种情况下shell于一个一般进程是相同的

    每次当shell启动时,它都将创建、更新或者添加自己的环境变量,将导致shell更新它的环境,同时也会影响所有继承这个环境的所有子进程

    注意:分配给环境变量的空间是受限的。创建太多的环境变量将引起空间溢出。

    如果一个脚本设置了环境变量,需要export它来通知脚本的环境。脚本只能对它产生的子进程export变量。一个从命令行被调用的脚本export的变量不会影响调用这个脚本的那个命令行shell的环境。

    positional parameters

    就是从命令行中传进来的参数 $0:脚本名 $1, 2 , 2, 2,…:第一个参数,第二个参数,第n个参数 ∗ 和 *和 @:所有的位置参数; ∗ : 把 所 有 位 置 参 数 当 做 一 个 参 数 ; *:把所有位置参数当做一个参数; :@:把所有参数分每个参数 $#:位置参数的个数

    Example 4.5 位置参数

    #!/bin/bash #scriptname.sh #作为用例,调用这个脚本至少需要10个参数 #如:./scriptname.sh 1 2 3 4 5 6 7 8 9 10 MINPARAMS=10 echo echo "The name of this script is \"$0\"." echo "The name of this script is \"`basename $0`\"." #去掉目录信息,具体见"basename"命令 echo if [ -n "$1" ];then echo "Parameter #1 is $1" fi if [ -n "$3" ];then echo "Parameter #2 is $2" fi if [ -n "$3" ];then echo "Parameter #3 is $3" fi #... if [ -n "${10}" ];then echo "Parameter #10 is ${10}" fi echo "----------" echo "All the command-line parameters are:"$*"" if [ $# -lt "$MINPARAMS" ];then echo echo "This script needs at least $MINPARAMS command-line arguments!" fi exit 0

    {}标记法是一种很好的使用位置参数的方法。这也需要间接引用(见Example 34.2)

    ${10}:大于9的位置参数必须出现在{}中。

    一些脚本可能会依赖于使用不用的调用名字,而表现出不同的行为,这样一般都需要判断$0,而其它的名字都是通过ln命令产生的链接。(具体参见Example 12.2)

    如果脚本需要一个命令行参数,而调用的时候没有这个参数,这就有可能造成分配一个空变量,这估计会引起问题。一种解决办法就是在这个位置参数和相关的变量后面都添加一个额外字符。具体见下面的例子

    variable1_=$1_ #而不是varible1=$1 #这将阻止一个错误额,即使在调用时没有这个位置参数。 critical_argument01=$variable1_ #这个扩展的字符是可以被消除的,像下面的操作 variable1=${variable1_/_/} #副作用就是$variable1_多了一个下划线 #一个解决这种问题的更简单做法就是,判断一下这个位置参数书否传递下来了 if [ -z $1 ];then exit $E_MISSING_POS_PARAM fi #但是上面的方法将可能产生一个意外的副作用 #参数替换的刚好办法应该是:${1:-$DefualtVal} #具体察看第九章"Parameter Substition"节

    Example 4.6 wh,whois 节点名字查询

    #!/bin/bash #ex18.sh #把这个脚本重命名为'wh',然后放到/usr/local/bin下 #需要3个符号链接 #ln -s /usr/local/bin/wh /usr/local/bin/wh-ripe #ln -s /usr/local/bin/wh /usr/local/bin/wh-cw #ln -s /usr/local/bin/wh /usr/local/bin/wh-radb E_NOARGS=65 if [ -z "$1" ];then echo "Usage: `basename $0` [domain-name]" exit $E_NOARGS fi #检查脚本名字,然后调用合适的服务器 case `basename $0` in "wh" ) whois $1@whois.ripe.net;; "wh-ripe" ) whois $1@whois.ripe.net;; "wh-radb" ) whois $1@whois.radb.net;; "wh-ce" ) whois $1@whois.ce.net;; * ) echo "Usage: `basename $0` [domain-name]";; esac exit $?

    shift

    重新分配位置参数,其实就是向左移动一个位置。 $1 <-- $2,$2 <-- $3,等等。老的$1将消失,但是$0不会改变。如果你是用了大量的位置参数,那么shift命令允许你存取超过10个参数。虽然{}表示法也允许这样

    Example 4.7 使用shift

    #!/bin/bash #shft.sh #使用shift来穿过所有的位置参数 #使用一些参数来调用它,如:./shft a b c def 123 admin until [ -z "$1" ] do echo -n "$1" shift done echo #换行 exit 0 #结果为:abcdef123admin

    注意:这里until循环和while循环相似,判断条件正好相反 until 当条件为假是循环 while 当条件为真时循环

    在将参数传递到函数中时,shift的工作方法也基本差不多。具体见Example 33.15

    Processed: 0.019, SQL: 9