文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>高级shell编程技巧4(转载)

高级shell编程技巧4(转载)

时间:2006-06-02  来源:lin_lin13

<meta http-equiv="CONTENT-TYPE" content="text/html; charset=utf-8"><title></title><meta name="GENERATOR" content="OpenOffice.org 2.0 (Linux)"><meta name="AUTHOR" content="lin lin"><meta name="CREATED" content="20060525;8284000"><meta name="CHANGEDBY" content="lin lin"><meta name="CHANGED" content="20060525;8323700"> <style> </style>

第4章 变量和参数的介绍

======================


4.1 变量替换

------------

$ 变量替换操作符

只有在变量被声明,赋值,unset或exported或者是在变量代表一个signal的时候,

变量才会是以本来的面目出现在脚本里.变量在被赋值的时候,可能需要使用"=",

read状态或者是在循环的头部.

在""中还是会发生变量替换,这被叫做部分引用,或叫弱引用.而在''中就不会发生变

量替换,这叫做全引用,也叫强引用.具体见第5章的讨论.


注意:$var与${var}的区别,不加{},在某些上下文将引起错误,为了安全,使用2.

具体见9.3节 参数替换.


Example 4-1. 变量赋值和替换

################################Start Script#######################################

1 #!/bin/bash

2

3 # 变量赋值和替换

4

5 a=375

6 hello=$a

7

8 #-------------------------------------------------------------------------

9 # 强烈注意,在赋值的前后一定不要有空格.

10 # 如果有空格会发生什么?

11

12 # 如果"VARIABLE =value",

13 # ^

14 #+ 脚本将尝试运行一个"VARIABLE"的命令,带着一个"=value"参数.

15

16 # 如果"VARIABLE= value",

17 # ^

18 #+ script tries to run "value" command with

18 #+ 脚本将尝试运行一个"value"的命令,带着

19 #+ the environmental variable "VARIABLE" set to "".

19 #+ 一个被赋成""值的环境变量"VARIABLE".

20 #-------------------------------------------------------------------------

21

22

23 echo hello # 没有变量引用,不过是个hello字符串

24

25 echo $hello

26 echo ${hello} # 同上

27

28 echo "$hello"

29 echo "${hello}"

30

31 echo

32

33 hello="A B C D"

34 echo $hello # A B C D

35 echo "$hello" # A B C D

36 # 就象你看到的echo $hello 和 echo "$hello" 将给出不同的结果.

37 # ^ ^

38 # Quoting a variable preserves whitespace.

38 # 引用一个变量将保留其中的空白,当然,如果是变量替换就不会保留了.

39

40 echo

41

42 echo '$hello' # $hello

43 # ^ ^

44 # 全引用的作用

45 #+ 将导致"$"变成一个单独的字符.

46

47 # 注意两种引用不同的效果

48

49

50 hello= # 设置为空值

51 echo "\$hello (null value) = $hello"

52 # 注意设置一个变量为空,与unset它,不是一回事,虽然看起来一样

53 #

54

55 # --------------------------------------------------------------

56

57 # 可以在同一行上设置多个变量.

58 #+ 要以空白分隔

59 # 小心,这会降低可读性,和可移植性.

60

61 var1=21 var2=22 var3=$V3

62 echo

63 echo "var1=$var1 var2=$var2 var3=$var3"

64

65 # 在老版本的"sh"上,可能会有问题.

66

67 # --------------------------------------------------------------

68

69 echo; echo

70

71 numbers="one two three"

72 # ^ ^

73 other_numbers="1 2 3"

74 # ^ ^

75 # 如果变量中有空白,那么引用就必要了.

76 #

77 echo "numbers = $numbers"

78 echo "other_numbers = $other_numbers" # other_numbers = 1 2 3

79 echo

80

81 echo "uninitialized_variable = $uninitialized_variable"

82 # Uninitialized变量为空值(根本就没赋值).

83 uninitialized_variable= # 声明,但是没被初始化

84 #+ 其实和前边设置为空值得作用是一样的.

85 echo "uninitialized_variable = $uninitialized_variable"

86 # 还是一个空值

87

88 uninitialized_variable=23 # 赋值

89 unset uninitialized_variable # Unset it.

90 echo "uninitialized_variable = $uninitialized_variable"

91 # 还是空值

92 echo

93

94 exit 0

################################End Script#########################################

注意: 一个空值变量,或者是根本就没声明的变量,在赋值之前使用它可能会引起问题.

但是还是可以用来做算术运算

################################Start Script#######################################

1 echo "$uninitialized" # (blank line)

2 let "uninitialized += 5" # Add 5 to it.

3 echo "$uninitialized" # 5

4

5 # 结论:

6 # 对于一个空值变量在做算术操作的时候,就好像它的值为0一样.

8 # This is undocumented (and probably non-portable) behavior.

7 # 这并没被文档化(可能是不可移植)的行为.

################################End Script#########################################

具体参考 Example 11-21



4.2 变量赋值

------------

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

不要与-eq混淆,那个是test,并不是赋值.

注意,=也可被用来做test操作,这依赖于上下文.


Example 4-2. 一般的变量赋值

################################Start Script#######################################

1 #!/bin/bash

2 # "裸体"变量

3

4 echo

5

6 # 变量什么时候是"裸体"的,比如前边少了$的时候.

7 # 当它被赋值的时候,而不是被引用的时候.

8

9 # 赋值

10 a=879

11 echo "The value of \"a\" is $a."

12

13 # 使用let赋值

14 let a=16+5

15 echo "The value of \"a\" is now $a."

16

17 echo

18

19 # 在for循环中

20 echo -n "Values of \"a\" in the loop are: "

21 for a in 7 8 9 11

22 do

23 echo -n "$a "

24 done

25

26 echo

27 echo

28

29 # 在read命令状态中

30 echo -n "Enter \"a\" "

31 read a

32 echo "The value of \"a\" is now $a."

33

34 echo

35

36 exit 0

################################End Script#########################################


Example 4-3. 变量赋值,一般的和比较特殊的

################################Start Script#######################################

1 #!/bin/bash

2

3 a=23 # Simple case

4 echo $a

5 b=$a

6 echo $b

7

8 # 现在让我们来点小变化

9

10 a=`echo Hello!` # 把echo命令的结果传给变量a

11 echo $a

12 # 注意,如果在命令扩展结构中使用一个(!)的话,在命令行中将不能工作

13 #+ 因为这触发了Bash的"历史机制".

14 # 但是,在校本里边使用的话,历史功能是被关闭的,所以就能够正常运行.

15

16

17 a=`ls -l` # 把ls -l的结果给a

18 echo $a # 别忘了,这么引用的话,ls的结果中的所有空白部分都没了(包括换行)

19 echo

20 echo "$a" # 这么引用就正常了,保留了空白

21 # (具体参阅章节"引用")

22

23 exit 0

################################End Script#########################################

使用$(...)机制进行的变量赋值(除去使用``来赋值的另外一种新方法).事实上这两种方法都是

命令替换的一种形式.

# 来自于/ect/rc.d/rc.local

R=$(cat /ect/redhat-release)

arch=$(uname -m)



4.3 Bash变量是不分类型的

------------------------

不像其他程序语言一样,Bash并不对变量区分"类型".本质上,Bash变量都是字符串.

但是依赖于上下文,Bash也允许比较操作和算术操作.决定这些的关键因素就是,变量中的值

是否只有数字.


Example 4-4 整型还是string?

################################Start Script#######################################

1 #!/bin/bash

2 # int-or-string.sh: 整形还是string?

3

4 a=2334 # 整型

5 let "a += 1"

6 echo "a = $a " # a = 2335

7 echo # 还是整型

8

9

10 b=${a/23/BB} # 将23替换成BB

11 # 这将把b变量从整型变为string

12 echo "b = $b" # b = BB35

13 declare -i b # 即使使用declare命令也不会对此有任何帮助,9.4节有解释

14 echo "b = $b" # b = BB35

15

16 let "b += 1" # BB35 + 1 =

17 echo "b = $b" # b = 1

18 echo

19

20 c=BB34

21 echo "c = $c" # c = BB34

22 d=${c/BB/23} # S将BB替换成23

23 # 这使得$d变为一个整形

24 echo "d = $d" # d = 2334

25 let "d += 1" # 2334 + 1 =

26 echo "d = $d" # d = 2335

27 echo

28

29 # 关于空变量怎么样?

30 e=""

31 echo "e = $e" # e =

32 let "e += 1" # 算术操作允许一个空变量?

33 echo "e = $e" # e = 1

34 echo # 空变量将转换成一个整型变量

35

36 # 关于未声明的变量怎么样?

37 echo "f = $f" # f =

38 let "f += 1" # 算术操作允许么?

39 echo "f = $f" # f = 1

40 echo # 未声明的变量将转换成一个整型变量

41

42

43

44 # 所以说Bash中的变量都是无类型的.

45

46 exit 0

################################End Script#########################################



4.4 特殊的变量类型

------------------

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 [email protected];;

26 "wh-ripe") whois [email protected];;

27 "wh-radb") whois [email protected];;

28 "wh-cw" ) whois [email protected];;

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页.



相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载