免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 20121 | 回复: 10
打印 上一主题 下一主题

shell基础第十四篇-环境和shell变量 [复制链接]

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-11-19 20:24 |只看该作者 |倒序浏览
为使s h e l l编程更有效,系统提供了一些s h e l l变量。s h e l l变量可以保存诸如路径名、文件
名或者一个数字这样的变量名。s h e l l将其中任何设置都看做文本字符串。
有两种变量,本地和环境。
补充:这里似乎不全面,我们似乎更倾向于这种分法,应该是用户自定义变量,通常我们使用小写字符表示,和环境变量,通常用全部大写字符表示,比如PATH,这是我们执行命令的搜索路径。LIBRARY_PATH链接库的路径。还有局部变量,也就是上面说的本地变量。只是在一定的区域范围内有效。
这样子的话,才好区分。

严格地说可以有4种,但其余两种是只读的,可以认为是特殊
变量,它用于向s h e l l脚本传递参数。
本章内容有:
• shell变量。
• 环境变量。
• 变量替换。
• 导出变量。
• 特定变量。
• 向脚本传递信息。
• 在系统命令行下使用位置参数。


什么是shell变量?
变量可以定制用户本身的工作环境。使用变量可以保存有用信息,使系统获知用户相关
设置。变量也用于保存暂时信息。例如:一变量为E D I TO R,系统中有许多编辑工具,但哪一
个适用于系统呢?将此编辑器名称赋给E D I TO R,这样,在使用c r o n或其他需要编辑器的应用
时,这就是你将一直使用的E D I TO R取值,并将之用作缺省编辑器。

变量的命名需要遵守什么规则?
简单概括来,有以下一些规则:
1、变量和变量的内容用"="来连接
2、等号两边不能直接解空格字符,如果接上了空格,这时候shell会把变量当作命令尝试执行,而找不到就会提示错误
3、变量名称只能是英文字符和数字和下划线,同时数字不能是开头字符。
4、若有空格字符,可以使用双引号或者单引号将内容结合起来。但是要注意,双引号内的变量可以保持变量的特性,单引号内的仅仅是一般字符。
5、必要时候以转义字符"\"将其他一些特殊字符变成一般符号。
6、export可以使一个变量编程环境变量
7、可以使用unset取消变量的定义



本地变量
本地变量在用户现在的s h e l l生命期的脚本中使用。例如,本地变量f i l e - n a m e取值为
l o o p . d o c,这个值只在用户当前s h e l l生命期有意义。如果在s h e l l中启动另一个进程或退出,此
值将无效。这个方法的优点就是用户不能对其他的s h e l l或进程设置此变量有效。
表1 4 - 1列出各种实际变量模式
使用变量时,如果用花括号将之括起来,可以防止s h e l l误解变量值,尽管不必一定要这样做,但这确实可用。
要设置一本地变量,格式为:
$ variable-name=valu或e $ { v a r i a b l e - n a m e = v a l u e }
注意,等号两边可以有空格。如果取值包含空格,必须用双引号括起来。s h e l l变量可以
用大小写字母。

                     表14-1 变量设置时的不同模式
Va r i a b l e - n a m e = v a l u e 设置实际值到v a r i a b l e - n a m e
Va r i a b l e - n a m e + v a l u e 如果设置了v a r i a b l e - n a m e,则重设其值
Va r i a b l e - n a m e : ? v a l u e 如果未设置v a r i a b l e - n a m e,显示未定义用户错误信息
Va r i a b l e - n a m e ? v a l u e 如果未设置v a r i a b l e - n a m e,显示系统错误信息
Va r i a b l e - n a m e : = v a l u e 如果未设置v a r i a b l e - n a m e,设置其值
Va r i a b l e - n a m e : - v a l u e 同上,但是取值并不设置到v a r i a b l e - n a m e,可以被替换


显示变量
使用e c h o命令可以显示单个变量取值,并在变量名前加$,例如:
  1. $ GREAT_PICTURE="die hard"
  2. $ echo ${GREAT_PICTURE}
  3. die hard
  4. $ DOLLAR=99
  5. $ echo ${DOLLAR}
  6. 99
  7. $ LAST_FILE=ZLPSO.txt
  8. $ echo ${LAST_FILE}
  9. ZLPSO.txt
复制代码
可以结合使用变量,下面将错误信息和环境变量L O G N A M E设置到变量e r r o r- m s g。
  1. $ ERROR_MSG=" Sorry this file does not exist user $LOGNAME"
  2. $ echo ${ERROR_MSG}
  3. Sorry this file does not exist user root
复制代码
上面例子中,s h e l l首先显示文本,然后查找变量$ L O G N A M E,最后扩展变量以显示整个
变量值。

清除变量
使用u n s e t命令清除变量。
unset variable-name
  1. $ PC=enterprise
  2. $ echo ${PC}
  3. enterprise
  4. $ unset PC
  5. $ echo ${PC}
复制代码
显示所有本地shell变量
  1. $ set
  2. ......
  3. BASH_VERSION='4.0.23(1)-release'
  4. COLORS=/etc/DIR_COLORS
  5. COLORTERM=gnome-terminal
  6. COLUMNS=80
  7. CVS_RSH=ssh
  8. DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-MmGXVtOFZ0,guid=604b8af6bd4ce1a0b825456b4ce79674
  9. DESKTOP_SESSION=gnome
  10. DIRSTACK=()
  11. DISPLAY=:0.0
  12. DOLLAR=99
  13. ......
复制代码
s e t输出可能很长。查看输出时可以看出s h e l l已经设置了一些用户变量以使工作环境更加
容易使用。

结合变量值
将变量并排可以使变量结合在一起:
  1. $ FIRST="Bruce "
  2. $ SURNAME=Willis
  3. $ echo ${FIRST}${SURNAME}
  4. Bruce Willis
复制代码
测试变量是否已经设置
有时要测试是否已设置或初始化变量。如果未设置或初始化,就可以使用另一值。此命
令格式为:
$ { v a r i a b l e : - v a l u e }
意即如果设置了变量值,则使用它,如果未设置,则取新值。例如:
  1. $ COLOUR=blue
  2. $ echo "The sky is ${COLOR:-grey} today"
  3. The sky is grey today
复制代码
变量c o l o u r取值b l u e,e c h o打印变量c o l o u r时,首先查看其是否已赋值,如果查到,则使
用该值。变量$COLOR没有设置,所以会打印后面的grey

上面的例子并没有将实际值传给变量,需使用下述命令完成此功能:
$ { v a r i a b l e : = v a l u e }
下面是一个更实用的例子。查询工资清单应用的运行时间及清单类型。在运行时间及类
型输入时,敲回车键表明用户并没有设置两个变量值,将使用缺省值( 0 3 : 0 0和We e k l y),并
传入a t命令中以按时启动作业。
  1. #!/bin/bash
  2. # vartest
  3. echo "what time do you wish start the payroll [03:00]:"
  4. read TIME
  5. echo " process to start at ${TIME:=03:00} OK"
  6. echo "Is it a monthly or weekly run [Weekly]:"
  7. read RUN_TYPE
  8. echo "Run type is ${RUN_TYPE:=Weekly}'
  9. at -f $RUN_TYPE $TIME
复制代码
在输入域敲回车键,输出结果如下:
what time do you wish start the payroll [03:00]:

process to start at 03:00 OK
Is it a monthly or weekly run [Weekly]:

Run type is Weekly


也可以编写脚本测试变量是否取值,然后返回带有系统错误信息的结果。下面的例子测
试变量f i l e是否取值。
  1. $ echo "The file is ${FILES:?}"
  2. bash: FILES: parameter null or not set
复制代码
以上结果可读性不好,但是可以加入自己的脚本以增加可读性。
  1. $ echo "The file is ${FILES:?" sorry cannot locate the variable files"}"
  2. bash: FILES:  sorry cannot locate the variable files
复制代码
测试变量是否取值,如果未设置,则返回一空串。方法如下:
$ { v a r i a b l e : + v a l u e }
使用下述方法初始化变量为空字符串。
v a r i a b l e = " "
$ D E T I N A T I O N = " "

使用变量来保存系统命令参数
可以用变量保存系统命令参数的替换信息。下面的例子使用变量保存文件拷贝的文件名
信息。变量s o u r c e保存p a s s w d文件的路径,d e s t保存c p命令中文件目标。
  1. $ SOURCE="/etc/passwd"
  2. $ DEST="/tmp/passwd.bak"
  3. $ cp ${SOURCE} ${DEST}
复制代码
下面例子中,变量d e v i c e保存磁带设备路径,然后用于在m t命令中倒带。
  1. $ DEVICE="/dev/rmt/0n"
  2. $ mt -f {DEVICE} rewind
复制代码
设置只读变量
如果设置变量时,不想再改变其值,可以将之设置为只读方式。如果有人包括用户本人
想要改变它,则返回错误信息。格式如下:
v a r i a b l e - n a m e = v a l u e
readonly variable-name
下面的例子中,设置变量为系统磁带设备之一的设备路径,将之设为只读,任何改变其值的操作将返回错误信息。
  1. $ TAPE_DEV="/dev/rmt/0n"
  2. $ echo ${TAPE_DEV}
  3. /dev/rmt/0n
  4. $ readonly TAPE_DEV
  5. $ TAPE_DEV="/dev/rmt/1n"
  6. bash: TAPE_DEV: readonly variable
复制代码
要查看所有只读变量,使用命令r e a d o n l y即可。
  1. $ readonly
  2. declare -ir BASHPID=""
  3. declare -ar BASH_VERSINFO='([0]="4" [1]="0" [2]="23" [3]="1" [4]="release" [5]="i386-redhat-linux-gnu")'
  4. declare -ir EUID="500"
  5. declare -ir PPID="2813"
  6. declare -r SHELLOPTS="braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor"
  7. declare -r TAPE_DEV="/dev/rmt/0n"
  8. declare -ir UID="500"
复制代码

论坛徽章:
11
金牛座
日期:2015-03-19 16:56:22数据库技术版块每日发帖之星
日期:2016-08-02 06:20:00数据库技术版块每日发帖之星
日期:2016-04-24 06:20:00数据库技术版块每日发帖之星
日期:2016-04-13 06:20:00IT运维版块每日发帖之星
日期:2016-04-13 06:20:00数据库技术版块每日发帖之星
日期:2016-02-03 06:20:00数据库技术版块每日发帖之星
日期:2015-08-06 06:20:00季节之章:春
日期:2015-03-27 15:54:57羊年新春福章
日期:2015-03-27 15:54:37戌狗
日期:2015-03-19 16:56:41数据库技术版块每日发帖之星
日期:2016-08-18 06:20:00
2 [报告]
发表于 2010-11-19 20:57 |只看该作者

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
3 [报告]
发表于 2010-11-19 21:22 |只看该作者
位置变量参数
本章开始提到有4种变量,本地、环境,还有两种变量被认为是特殊变量,因为它们是只
读的。这两种变量即为位置变量和特定变量参数。先来看一看位置变量。
如果要向一个s h e l l脚本传递信息,可以使用位置参数完成此功能。参数相关数目传入脚
本,此数目可以任意多,但只有前9个可以被访问,使用s h i f t命令可以改变这个限制。本书后
面将讲到s h i f t命令。参数从第一个开始,在第9个结束;每个访问参数前要加$符号。第一个
参数为0,表示预留保存实际脚本名字。无论脚本是否有参数,此值均可用。
如果向脚本传送Did You See Th e Full Mo o n信息,下面的表格讲解了如何访问每一个参
数。
$ 0 $ 1 $ 2 $ 3 $ 4 $ 5 $ 6 $ 7 $ 8 $ 9
脚本名字Did Yo u S e e T h e F u l l M o o n
在脚本中使用位置参数
在下面脚本中使用上面的例子。
  1. [mutter@localhost ~] $ cat param.sh
  2. #!/bin/bash
  3. # param
  4. echo "This is the script name                : $0"
  5. echo "This is the first parameter        : $1"
  6. echo "This is the second parameter        : $2"
  7. echo "This is the third parameter        : $3"
  8. echo "This is the fourth parameter        : $4"
  9. echo "This is the fifth parameter        : $5"
  10. echo "This is the sixth parameter        : $6"
  11. echo "This is the seventh parameter        : $7"
  12. echo "This is the eighth parameter        : $8"
  13. echo "This is the ninth parameter        : $9"
复制代码
运行结果如下:
  1. [mutter@localhost ~] $ sh param.sh Did You See The Full Moon
  2. This is the script name                : param.sh
  3. This is the first parameter        : Did
  4. This is the second parameter        : You
  5. This is the third parameter        : See
  6. This is the fourth parameter        : The
  7. This is the fifth parameter        : Full
  8. This is the sixth parameter        : Moon
  9. This is the seventh parameter        :
  10. This is the eighth parameter        :
  11. This is the ninth parameter        :
复制代码
这里只传递6个参数,7、8、9参数为空,正像预计的那样。注意,第一个参数表示脚本
名,当从脚本中处置错误信息时,此参数有很大作用。
下面的例子返回脚本名称。
  1. [mutter@localhost ~] $ cat param2.sh
  2. #!/bin/bash
  3. echo "Hello world this is $0 calling"
复制代码
  1. [mutter@localhost ~] $./param2.sh
  2. Hello world this is ./param2.sh calling
复制代码
注意$ 0返回当前目录路径,如果只返回脚本名,在b a s e n a m e命令下参数设为$ 0,刚好得
到脚本名字。
  1. [mutter@localhost ~] $ cat param2.sh
  2. #!/bin/bash
  3. echo "Hello world this is `basename $0` calling"
复制代码
  1. [mutter@localhost ~] $./param2.sh
  2. Hello world this is param2.sh calling
复制代码
向系统命令传递参数
可以在脚本中向系统命令传递参数。下面的例子中,在f i n d命令里,使用$ 1参数指定查
找文件名。
  1. $ cat findfile.sh
  2. #!/bin/bash
  3. # findfile
  4. find / -name $1 -print
复制代码
  1. $ ./findfile passwd
  2. /etc/passwd
  3. /usr/bin/passwd
复制代码
每台机器的输出结果可能不同。

另一个例子中,以$ 1向g r e p传递一个用户i d号, g r e p使用此i d号在p a s s w d中查找用户全
名。
  1. [mutter@localhost ~] $ cat who_is.sh
  2. #!/bin/bash
  3. # who_is
  4. grep $1 /etc/passwd | awk -F: '{print $4}'
  5. [mutter@localhost ~] $ sh who_is.sh mutter
  6. 502
复制代码
特定变量参数
既然已经知道了如何访问和使用s h e l l脚本中的参数,多知道一点相关信息也是很有用的,
有必要知道脚本运行时的一些相关控制信息,这就是特定变量的由来。共有7个特定变量,见
表1 4 - 2。
表14-2 特定s h e l l变量
$ # 传递到脚本的参数个数
$ * 以一个单字符串显示所有向脚本传递的参数。与位置变量不同,此选项参数可超过9个
$ $ 脚本运行的当前进程I D号
$ ! 后台运行的最后一个进程的进程I D号
$ @ 与$ #相同,但是使用时加引号,并在引号中返回每个参数
$ - 显示s h e l l使用的当前选项,与s e t命令功能相同
$ ? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。


现在来修改脚本p a r a m并替换各种特定变量,与以前的例子不同,用不同的传递文本重新
运行脚本。
  1. [mutter@localhost ~] $ cat param.sh
  2. #!/bin/bash
  3. # param
  4. echo "This is the script name                : $0"
  5. echo "This is the first parameter        : $1"
  6. echo "This is the second parameter        : $2"
  7. echo "This is the third parameter        : $3"
  8. echo "This is the fourth parameter        : $4"
  9. echo "This is the fifth parameter        : $5"
  10. echo "This is the sixth parameter        : $6"
  11. echo "This is the seventh parameter        : $7"
  12. echo "This is the eighth parameter        : $8"
  13. echo "This is the ninth parameter        : $9"
  14. echo "The number of arguments passed        : $#"
  15. echo "Show all arguments                : $*"
  16. echo "Show me my process ID                : $"
  17. echo "Show me the arguments in quotes        :" "$@"
  18. echo "Did my script go with any errors        : $?"
  19. [mutter@localhost ~] $ sh param.sh Merry Christmas Mr Lawrence
  20. This is the script name                : param.sh
  21. This is the first parameter        : Merry
  22. This is the second parameter        : Christmas
  23. This is the third parameter        : Mr
  24. This is the fourth parameter        : Lawrence
  25. This is the fifth parameter        :
  26. This is the sixth parameter        :
  27. This is the seventh parameter        :
  28. This is the eighth parameter        :
  29. This is the ninth parameter        :
  30. The number of arguments passed        : 4
  31. Show all arguments                : Merry Christmas Mr Lawrence
  32. Show me my process ID                : 7564
  33. Show me the arguments in quotes        : Merry Christmas Mr Lawrence
  34. Did my script go with any errors        : 0
复制代码
特定变量的输出使用户获知更多的脚本相关信息。可以检查传递了多少参数,进程相应
的I D号,以免我们想杀掉此进程。

最后的退出状态
注意,$ ?返回0。可以在任何命令或脚本中返回此变量以获得返回信息。基于此信息,可
以在脚本中做更进一步的研究,返回0意味着成功,1为出现错误。
下面的例子拷贝文件到/ t m p,并使用$ ?检查结果。
  1. [mutter@localhost ~] $ cp ok.txt /tmp
  2. cp: cannot stat `ok.txt': No such file or directory
  3. [mutter@localhost ~] $ echo $?
  4. 1
复制代码
使用$ ?检验返回状态,可知脚本有错误,但同时发现c p:c a n n o t . . .,因此检验最后退出状
态已没有必要。在脚本中可以用系统命令处理输出格式,要求命令输出不显示在屏幕上。为
此可以将输出重定向到/ d e v / n u l l,即系统b i n中。现在怎样才能知道脚本正确与否?好,这时
可以用最后退出状态命令了。请看上一个例子的此形式的实际操作结果。
  1. [mutter@localhost ~] $ cp ok.txt /tmp >/dev/null 2>&1
  2. [mutter@localhost ~] $ echo $?
  3. 1
复制代码
通过将包含错误信息的输出重定向到系统b i n中,不能获知最后命令返回状态,但是通过
使用$ !,(其返回值为1)可知脚本失败。
检验脚本退出状态时,最好将返回值设置为一个有意义的名字,这样可以增加脚本的可
读性。
  1. [mutter@localhost ~] $ cp ok.txt /tmp >/dev/null 2>&1
  2. [mutter@localhost ~] $ cp_status=$?
  3. [mutter@localhost ~] $ echo $cp_status
  4. 1
复制代码

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
4 [报告]
发表于 2010-11-19 21:23 |只看该作者
小结
变量可以使s h e l l编程更容易。它能够保存输入值并提高效率。s h e l l变量几乎可以包含任
何值。特定变量增强了脚本的功能并提供了传递到脚本的参数的更多信息。
END
第十四篇-环境和shell变量结束

论坛徽章:
0
5 [报告]
发表于 2010-11-19 21:51 |只看该作者
楼主辛苦啦

论坛徽章:
2
技术图书徽章
日期:2013-10-30 14:37:252015年亚洲杯之伊朗
日期:2015-04-30 13:37:02
6 [报告]
发表于 2010-11-20 02:00 |只看该作者
好长,好累。捧一下楼主的场。。

论坛徽章:
0
7 [报告]
发表于 2011-08-17 17:08 |只看该作者
好东西,继续顶

论坛徽章:
0
8 [报告]
发表于 2011-12-01 01:10 |只看该作者
大力支持楼主啊 真的辛苦啦 收藏一下谢谢了

论坛徽章:
11
CU十二周年纪念徽章
日期:2013-10-24 15:41:342015年辞旧岁徽章
日期:2015-03-03 16:54:15丑牛
日期:2015-01-14 10:36:40技术图书徽章
日期:2015-01-12 15:46:11白羊座
日期:2014-11-14 09:35:36狮子座
日期:2014-10-30 13:18:49巳蛇
日期:2014-10-11 12:52:08子鼠
日期:2014-09-28 14:11:06双鱼座
日期:2014-04-22 13:05:48午马
日期:2014-02-11 17:58:002015年迎新春徽章
日期:2015-03-04 09:55:28
9 [报告]
发表于 2012-10-30 11:17 |只看该作者
大力支持,感谢!

论坛徽章:
2
水瓶座
日期:2014-02-28 14:20:09辰龙
日期:2014-06-16 13:18:51
10 [报告]
发表于 2014-02-20 17:36 |只看该作者
阅读完毕,做个记号
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP