闇の光

读书笔记 经验感受

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

Commands(2)

export

export命令能够将变量命名为在子shell中的参数变量。默认状况下,在一个shell生成的变量是不能被此shell的子shell所调用的。而export命令可以通过它的参数生成一个环境变量,这个参数可以被在当前程序下所调用的其他脚本和程序所发现。更专业些来说,就是说来自于该shell的子进程中的环境变量都是由此shell所导出的变量构成。下面是连个脚本export1和export2的示例:

首先,export2
#!/bin/sh

echo "$foo"
echo "$bar"
其次,export1
#!/bin/sh

foo="The first meta-syntactic variable"
export bar="The second meta-syntactic variable"

export2
最后,运行脚本:
$ ./export1
结果显示:
The second meta-syntactic variable

一旦一个变量被shell所导出,那么由这个shell所派生的或者在该shell中依次调用的脚本中就都是可见的。如果脚本export2调用了另外一个的脚本,那么对于另外一个脚本而言,bar这个变量的值依旧是可见的。
注:我们可以通过set -a 或 set -allexport来导出所有在其后的变量。

expr

expr命令可以给它的参数像一个表达式一样赋值。它在最简单的算术运算上的普遍用法如下面的形式所示:

x=`expr $x + 1`

``(backtick)反引号字符作用是令x得到expr $x + 1的结果,你也可以用$( )来代替反引号,比如:x=(expr $x + 1)

expr很强大,它可以执行一些表达式赋值操作。以下是一些主要的表达式赋值操作:

Expression EvaluationDescription
expr1 | expr2expr1非零时返回expr1,否则返回expr2
expr1 & expr2表达式中任意一个为0则返回0,否则返回expr1
expr1 = expr2相等
expr1 > expr2大于
expr1 >= expr2大于等于
expr1 < expr2小于
expr1 <= expr2小于等于
expr1 != expr2不等于
expr1 + expr2相加
expr1 - expr2相减
expr1 * expr2相乘
expr1 / expr2整数相除
expr1 % expr2整数求模

在新的脚本写法中,更多使用$((...))来代替expr,我们将在以后的章节里面介绍。

printf

printf命令只能在比较近的shell版本里面运行。X/Open建议我们优先使用printf来生成格式化的输出,而不是echo,尽管好像只有一小部分人采纳了该建议。

printf的语法规则:

printf "format string" parameter1 parameter2 ...

格式化字符串(format string)同C或C++中使用相类似,只是有一些限制。最主要的区别就是shell不支持精度小数点,所有的算术运算在shell中都是以整数来运算。格式化字符串由字母、转义序列以及转义字符所组成,除了%和\外,所有的字符都可以精确地输出。

下面就是支持的转义序列:

Escape SequenceDescription
\"双引号
\\反斜杠
\a警报(发出警铃声或蜂鸣声)
\b退格
\f形成输入字符
\n新行字符
\r回车
\tTab字符
\v垂直Tab
\ooo由八进制表示的单个字符
\xHH由十六进制表示的单个字符

转义字符是相当复杂的,因此我们只在此列出一些普遍的用法。转移字符符由一个%字符跟一个转义字符所组成。下面是主要的转义字符:

Conversion SpecifierDescription
D输出一个十进制数值
C输出一个字符
S输出一个字符串
%输出%字符

格式化字符串被用来解释剩余的参数和输出结果,如下例所示:

$ printf "%s\n" hello
hello
$ printf "%s %d\t%s" "Hi There" 15 people
Hi There 15    people

return

return命令是用来促使函数的返回,这一点在以前所看过的函数那里就提及过了。return在脚本调用函数之后会带着一个单一有效的数值参数返回,如果没有指定返回参数,return默认将返回最后运行的命令的退出状态。

set

set命令是用来给shell设定参数变量的值,这对于输出由空格来隔离的命令使用域来说,是一种有效的方法。假设你想要在一个shell脚本中使用当前月份的名称,系统为我们提供了date命令,在其输出中,月份只是其中的一个字符串,因此我们需要把它从中分离出来。这时,我们就需要通过set命令和$(...)组合运行date命令并返回我们所要的结果。在date命令的输出中,月份所占的字符串是它的第二个参数。示例如下:

#!/bin/sh

echo the date is $(date)
echo $(date)
echo The month is $2

exit 0

上面的程序设定date命令输出的参数列,之后根据位置参数$2得到月份。

注意:我们使用date命令的一个小小示例来展示如何提取位置参数。由于date命令对本地系统语言的敏感,事实上我们在提取月份的名称时,会使用date +%B来获得。date命令用很多的格式化参数选项,要了解更多请翻阅相关的手册。

我们也可以使用set命令通过shell的参数来控制该shell所运行的方式。最普遍的用法是:set -x,它可以显现出当前运行的命令的踪迹。我们将在以后有关debugging的章节再深入讨论set以及set的选项。

shift

shift命令用来将所有的参数变量一个一个地向下移动,也就是$2变成了$1,$3变成了$2,一直到最末位。当然,前面的$1将被丢弃,不过$0保持不变。如果调用shift命令时指定了一个数值参数,那么参数就移动对应的空格。至于其他的变量,比如:$*,$@以及$#同样会被参数变量新的排列所改变。

shift经常用来扫描一个脚本中所包含的参数,如果你的脚本需要10个或更多的参数,你可以使用shift来访问第十个以及其后的。例如,你可以像这样来扫描所有的位置参数:

#!/bin/sh

while [ "$1" != "" ]; do
    echo "$1"
done

exit 0

trap

trap命令被用来指定在收到信号时所要进行的动作,一种普遍的用法是在脚本被中断时对脚本所做的处理工作。由于历史原因,shell总是用数字来标示信号,不过在新的脚本里,可以通过#include文件signal.h的方式,在省略SIG的前缀的情况下以名字来标示。如果想要看信号的数字以及对应的名字,我们只需在命令提示符下键入trap -l即可。

trap可以通过在其后紧跟信号名称的方式来捕获信号:trap command signal记住脚本正常中断都是从上到下进行,因此我们必须在想要保护的脚本代码片段前指定trap命令。

要重新设定一个trap的条件为默认条件,只需简单指定命令为-。而要忽略一个信号,则需要设定命令为空串''。一个不带参数的trap命令只输出当前的动作列表。

下表将列出一些可以被捕获的比较重要的X/Open标准信号,它们都和圆括号中的传统信号数字在一起。

SignalDecription
HUP(1)挂起;通常当一个终端离线或用户退出是发送
INT(2)中断;通常在按下Ctrl+C时发送
QUIT(3)退出;通常在按下Ctrl+\时发送
ABRT(6)中止;通常在一些严重的运行错误时发送
ALRM(4)警报;通常用于处理超时
TERM(15)终止;通常当系统关闭时发送

下面的脚本示范了一些简单的信号处理:
#!/bin/sh

trap 'rm -f /tmp/my_tmp_file_$$' INT
echo creating file /tmp/my_tmp_file_$$
date > /tmp/my_tmp_file_$$

echo "press interrupt (Crtl+C) to interrupt ....."
while [ -f /tmp/my_tmp_file_$$ ]; do
    echo File exists
    sleep 1
done
echo The file no longer exists

trap INT
echo creating file /tmp/my_tmp_file_$$
date > /tmp/my_tmp_file_$$

echo "press interrupt (Crtl+C) to interrupt ....."
while [ -f /tmp/my_tmp_file_$$ ]; do
    echo File exists
    sleep 1
done

echo we never get here
exit 0
运行上面的脚本,当你按下Ctrl+C时,或者时其他用来中断的按键时,你将得到类似下面的输出:
creating file /tmp/my_tmp_file_141
press interrupt (Ctrl+C) to interrupt .....
File exists
File exists
File exists
File exists
The file no longer exists
creating file /tmp/my_tmp_file_141
press interrupt (Ctrl+C) to interrupt .....
File exists
File exists
File exists
File exists

unset

unset命令的功能是从环境中删除变量或函数,不过它不能删除shell自己所定义的只读变量,比如IFS。另外,unset命令不是经常被使用。

下面的脚本会先输出Hello World,之后输出一个新行,代码如下:
#!/bin/sh
foo="Hello World"
echo $foo

unset foo
echo $foo
posted on 2008-03-11 16:58  taizi  阅读(405)  评论(0编辑  收藏  举报