变量和参数内容摘要:#如果variable是一个变量名, 那么$variable就是引用这个变量的值.#在双引号( " " )中的变量仍然具有变量替换功能,在单引号( ' ' )中的变量无效.#$variable 是 ${variable}的简写形式.1 #!/bin/bash
2 #-------------------------------------------------------------------------
3 a=375
4 hello=$a
5 # 为变量赋值
6 #-------------------------------------------------------------------------
7 # 强烈注意, 在赋值的时候, 等号前后一定不要有空格,看下面的例子:
8 #
9 # "VARIABLE =value" #-bash:VARIABLE: command not found
10 # ^
11 # 此时脚本将尝试运行一个名为"VARIABLE"的命令, 带着一个"=value"参数.
12 #
13 # "VARIABLE= value" #-bash:value: command not found
14 # ^
15 # 此时脚本将尝试运行一个名为"value"的命令
16 # 并且带着一个被赋值成""的环境变量"VARIABLE".
17 #-------------------------------------------------------------------------
18 echo hello
19 # 没有引用变量, 只是hello字符串.
20 echo $hello
21 echo ${hello}
22 # 以上两种引用变量方式都是正确的,${}是完整的引用方式.
23 echo "$hello"
26 echo "${hello}"
27 # 双引号(" ")中变量引用是有效的.
28 #
29 hello="A B C D"
30 echo $hello # A B C D
31 echo "$hello" # A B C D
32 # echo $hello 和 echo "$hello" 将给出不同的结果.
33 # ===============================================================
34 # 引用一个变量将保留其中的空白,如果是变量替换就不会保留了.
39 # ===============================================================
40 #
41 echo '$hello' # $hello
42 # ^ ^
43 # 单引号(' ')将会导致"$"被解释为普通的字符,而不是变量前缀.
44 #
45 # 特别注意这两种引用所产生的不同效果.
46 #
47 hello= # 设置为空值.
48 echo "/$hello (null value) = $hello"
49 # 注意设置一个变量为null, 与unset这个变量, 并不是一回事
50 #+ 虽然最终的结果相同.
51 # --------------------------------------------------------------
52 #
53 # 可以在同一行上设置多个变量,但是必须以空白进行分隔.
54 # 慎用, 这么做会降低可读性, 并且不可移植.
55 #
56 var1=21 var2=22 var3=23
57 #
58 echo "var1=$var1 var2=$var2 var3=$var3"
59 #
60 # 在老版本的"sh"上可能会引起问题.
61 # --------------------------------------------------------------
62 #
63 numbers="one two three"
64 # ^ ^
65 other_numbers="1 2 3"
66 # ^ ^
67 # 如果在变量中存在空白,那么就必须加上引用.
68 # other_numbers=1 2 3 # 给出一个错误消息.
69 echo "numbers = $numbers"
70 echo "other_numbers = $other_numbers" # other_numbers = 1 2 3
71 # 也可以采用将空白转义的方法.
72 mixed_bag=2/ ---/ Whatever
73 # ^ ^ 在转义符后边的空格(/).
74 #
75 echo "$mixed_bag" # 2 --- Whatever
76 #
77 echo "uninitialized_variable = $uninitialized_variable"
78 # Uninitialized_variable变量为null(就是没有值).
79 uninitialized_variable= # 声明, 但是没有初始化这个变量,
80 # # 其实和前边设置为空值的作用是一样的.
81 echo "uninitialized_variable = $uninitialized_variable"
82 # # 还是一个空值.
83 #
84 uninitialized_variable=23 # 赋值.
85 unset uninitialized_variable # Unset这个变量.
86 echo "uninitialized_variable = $uninitialized_variable"
87 # # 还是一个空值.
88 exit 0
#一个未初始化的变量将会是"null"值 - 就是未赋值(但并不是代表值是0!).
#在给变量赋值之前就使用这个变量通常都会引起问题.
1 echo "$uninitialized" # (blank line)
2 let "uninitialized += 5" # Add 5 to it.
3 echo "$uninitialized" # 5
4
5 # 结论:
6 # 一个未初始化的变量是没有值的,
7 # 但是在做算术操作的时候, 这个未初始化的变量看起来值为0.
8 # 这是一个未文档化(并且可能不具可移植性)的行为.
=
#赋值操作(前后都不能有空白)
#因为=和-eq都可以用做条件测试操作, 所以不要与这里的赋值操作相混淆.
#注意: =既可以用做条件测试操作, 也可以用于赋值操作, 这需要视具体情况而定.
简单的变量赋值:
1 #!/bin/bash
2 #
3 # 变量什么时候是"裸体"的, 比如前边少了$的时候?
4 # 当它被赋值的时候, 而不是被引用的时候.
5 #
6 a=879
7 echo "The value of /"a/" is $a."
8 #
9 # 使用'let'赋值
10 let a=16+5
11 echo "The value of /"a/" is now $a."
12 #
13 # 在'for'循环中(事实上, 这是一种伪赋值):
14 echo -n "Values of /"a/" in the loop are: "
15 for a in 7 8 9 11
16 do
17 echo -n "$a "
18 done
19 #
20 # 使用'read'命令进行赋值(这也是一种赋值的类型):
21 echo -n "Enter /"a/" "
22 read a
23 echo "The value of /"a/" is now $a."
24 #
25 exit 0
简单和复杂, 两种类型的变量赋值:
1 #!/bin/bash
2 #
3 a=23 # 简单的赋值
4 echo $a
5 b=$a
6 echo $b
7 #
8 # 现在让我们来点小变化(命令替换).
9 a=`echo Hello!` # 把'echo'命令的结果传给变量'a'
10 echo $a
11 # 注意, 如果在一个命令替换结构中包含一个(!)的话,
12 # 那么在命令行下将无法工作.
13 # 因为这触发了Bash的"历史机制."
14 # 但是, 在脚本中使用的话, 历史功能是被禁用的, 所以就能够正常的运行.
15 #
16 a=`ls -l` # 把'ls -l'的结果赋值给'a'.
17 echo $a # 然而, 如果没有引号的话将会删除ls结果中多余的tab和换行符.
18 #
19 echo "$a" # 如果加上引号的话, 那么就会保留ls结果中的空白符.
20 #
21 exit 0
#使用$(...)机制来进行变量赋值(这是一种比后置引用(反引号`)更新的一种方法).
#事实上这两种方法都是命令替换的一种形式.
1 # From /etc/rc.d/rc.local
2 R=$(cat /etc/redhat-release)
3 arch=$(uname -m)
# Bash并不对变量区分"类型". 本质上, Bash变量都是字符串.
# 但是依赖于具体情况, Bash也允许比较操作和整数操作. 其中的关键因素是,
# 变量中的值是否只有数字.
1 #!/bin/bash
2 #整型还是字符串?
3 #
4 a=2334 # 整型.
5 let "a += 1"
6 echo "a = $a " # a = 2335
7 echo # 还是整型.
8 #
9 b=${a/23/BB} # 将"23"替换成"BB".
10 # # 这将把变量b从整型变为字符串.
11 echo "b = $b" # b = BB35
12 declare -i b # 即使使用declare命令也不会对此有任何帮助.
13 echo "b = $b" # b = BB35
14
15 let "b += 1" # BB35 + 1 =
16 echo "b = $b" # b = 1
17 echo
18 #
19 c=BB34
20 echo "c = $c" # c = BB34
21 d=${c/BB/23} # 将"BB"替换成"23".
22 # # 这使得变量$d变为一个整形.
23 echo "d = $d" # d = 2334
24 let "d += 1" # 2334 + 1 =
25 echo "d = $d" # d = 2335
26 echo
27 #
28 # null变量会如何呢?
29 e=""
30 echo "e = $e" # e =
31 let "e += 1" # 算术操作允许一个null变量?
32 echo "e = $e" # e = 1
33 echo # null变量将被转换成一个整型变量.
34 #
35 # 如果没有声明变量会怎样?
36 echo "f = $f" # f =
37 let "f += 1" # 算术操作能通过么?
38 echo "f = $f" # f = 1
39 echo # 未声明的变量将转换成一个整型变量.
40 #
41 # 所以说Bash中的变量都是不区分类型的.
42 #
43 exit 0
#不区分变量的类型既是幸运的事情也是不幸的事情.它允许你在编写脚本的时候更加的灵
#活,并且可以让你能够更容易的编写代码. 然而, 这也很容易产生错误,并且让你养成糟
#糕的编程习惯.因此程序员就承担了区分脚本中变量类型的责任. Bash是不会为你区分变
#量类型的.
#局部变量
#这种变量只有在代码块或者函数中可见.
#这种变量将影响用户接口和shell的行为.
#在通常情况下, 每个进程都有自己的"环境", 这个环境是由一组变量组成的,这些变量中
#存有进程可能需要引用的信息.在这种情况下, shell与一个一般的进程没什么区别.
#每次当一个shell启动时, 它都将创建适合于自己环境的shell变量. 更新或者添加一个新
#的环境变量, shell都会立刻更新它自己的环境(更改或增加的变量会立即生效), 并且所有
#的shell子进程(即这个shell所执行的命令)都会继承这个环境. (确切说应该是后继生成的
#子进程才会继承Shell的新环境变量, 已经运行的子进程并不会得到它的新环境变量).分配
#给环境变量的空间是有限的. 创建太多环境变量, 或者给一个环境变量分配太多的空间都
#会引起错误.
1 bash$ eval "`seq 10000 | sed -e 's/.*/export var&=ZZZZZZZZZZZZZZ/'`"
2 bash$ du
3 bash: /usr/bin/du: Argument list too long
#如果一个脚本要设置一个环境变量, 就需要将变量"export"出来, 使之成为环境变量.一个
#脚本只能够export变量到这个脚本所产生的子进程,也就是说只能够对这个脚本所产生的
#命令和进程起作用.如果脚本是从命令行中调用的, 那么这个脚本所export的变量是不能影
#响命令行环境的. 就是说, 子进程的export变量是不能影响父进程的环境的.
#从命令行传递到脚本的参数: $0, $1, $2, $3 . . .
#$0 是脚本文件自身的名字.
#$1 是第一个参数.
#$2 是第二个参数.
#$3 是第三个参数, 然后是第四个.
#$9 之后的位置参数就必须用大括号括起来, 比如, ${10}, ${11}, ${12}.
#两个比较特殊的变量$*和$@ 表示所有的位置参数.
1 #!/bin/bash
2 #3 # 作为用例, 调用这个脚本至少需要10个参数, 比如:4 # ./scriptname 1 2 3 4 5 6 7 8 9 105 MINPARAMS=106 echo7 echo "The name of this script is /"$0/"."8 # ./表示当前目录9 echo "The name of this script is /"`basename $0`/"."10 # 去掉路径名, 只剩下文件名.11 echo12 #13 if [ -n "$1" ] # 测试变量被引用.14 then15 echo "Parameter #1 is $1" # 需要引用才能够转义"#" .16 fi17 #18 if [ -n "$2" ]19 then20 echo "Parameter #2 is $2"21 fi22 #23 if [ -n "$3" ]24 then25 echo "Parameter #3 is $3"26 fi27 #28 # ...29 #30 #31 if [ -n "${10}" ] # 大于$9的参数必须用{}括起来.32 then33 echo "Parameter #10 is ${10}"34 fi35 #36 echo "-----------------------------------"37 echo "All the command-line parameters are: "$*""38 #39 if [ $# -lt "$MINPARAMS" ]40 then41 echo42 echo "This script needs at least $MINPARAMS command-linearguments!"43 fi44 #45 echo46 #47 exit 0
#{}标记法提供了一种提取从命令行传递到脚本的最后一个位置参数的简单办法. 但是这种方
#法同时还需要使用间接引用.
1 args=$# # 位置参数的个数.
2 lastarg=${!args}3 # 或者: lastarg=${!#}#注意, 不能直接使用 lastarg=${!$#} , 这会产生错误.一些脚本可能会依赖于使用不同的#调用名字, 来表现出不同的行为. 如果想要达到这种目的, 一般都需要在脚本中检查 $0 .#因为脚本只能够有一个真正的文件名, 如果要产生多个名字, 必须使用符号链接.
#如果脚本需要一个命令行参数,而在调用的时候, 这个参数没被提供, 那么这就可能造成给
#这个参数赋一个null变量, 通常情况下,这都会产生问题.一种解决这个问题的办法就是使用
#添加额外字符的方法, 在使用这个位置参数的变量和位置参数本身的后边全部添加同样的额
#外字符.
1 variable1_=$1_ # 而不是 variable1=$1
2 # 这将阻止报错, 即使在调用时没提供这个位置参数.3 #4 critical_argument01=$variable1_5 #6 # 这个扩展的字符是可以被消除掉的, 就像这样.7 variable1=${variable1_/_/}8 # 副作用就是$variable1_多了一个下划线.9 # 这里使用了参数替换模版的一种形式.10 #(在一个删除动作中, 节省了一个替换模式.)11 #12 # 处理这个问题的一个更简单的办法就是13 # 判断一下这个位置参数是否传递下来了.14 if [ -z $1 ]15 then16 exit $E_MISSING_POS_PARAM17 fi18 #19 #20 # 然而, 象Fabian Kreutz所指出的那样,21 # 上边的方法将可能产生一个意外的副作用.22 # 参数替换才是更好的方法:23 # ${1:-$DefaultVal}24 # 具体参见"参数替换"的相关章节,在"变量重游"那章.
wh, whois节点名字查询
1 #!/bin/bash2 # ex18.sh3 #4 # 是否'whois domain-name'能够找到如下3个服务之一:5 # ripe.net, cw.net, radb.net6 #7 # 把这个脚本重命名为'wh', 然后放到/usr/local/bin目录下.8 #9 # 需要符号链接:10 # ln -s /usr/local/bin/wh /usr/local/bin/wh-ripe11 # ln -s /usr/local/bin/wh /usr/local/bin/wh-cw12 # ln -s /usr/local/bin/wh /usr/local/bin/wh-radb13 #14 E_NOARGS=6515 #16 #17 if [ -z "$1" ]18 then19 echo "Usage: `basename $0` [domain-name]"20 exit $E_NOARGS21 fi22 #23 # 检查脚本名字, 然后调用合适的服务.24 case `basename $0` in # Or: case ${0##*/} in25 "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 esac31 #32 exit $?
#shift命令会重新分配位置参数, 其实就是把所有的位置参数都向左移动一个位置.
#$1 <--- $2, $2 <--- $3, $3 <--- $4等.原来的$1就消失了, 但是$0 (脚本名)是不
#会改变的. 如果传递了大量的位置参数到脚本中, 那么shift命令允许你访问的位置参数的
#数量超过10个, 当然{}标记法也提供了这样的功能.
使用shift命令
1 #!/bin/bash2 # 使用'shift'来逐步存取所有的位置参数.3 #4 # 给脚本命个名, 比如shft,5 # 然后给脚本传递一些位置参数, 比如:6 # ./shft a b c def 23 skidoo7 #8 until [ -z "$1" ] # 直到所有的位置参数都被存取完...9 do10 echo -n "$1 "11 shift12 done13 #14 echo # 额外的换行.15 #16 exit 0
#在将参数传递到函数中的时候, shift命令的工作方式也差不多. 参考例子 33-15.
注意事项
#$0参数是由调用这个脚本的进程所设置的. 按照约定, 这个参数一般就是脚本的名字. 具
#体请参考execv的man页.
变量和参数
最新推荐文章于 2024-01-07 10:43:15 发布