shell 中函数的使用
1 . shell中函数的基本使用,我们创建一个文件命名为hellloWorld.bash,在文件中输入以下内容
#!/bin/bash
# shell中的函数
func () {
echo "step 2"
return
}
# 主要的程序是下边的语句
echo "step 1"
#调用func函数
func
echo "step 3"
2 . 在HTML的输出文本中调用一个函数
#!/bin/bash
# Program to output a system information page
FUN="这是一个函数的内容"
report_uptime () {
echo $FUN
return
}
report_disk_space () {
echo "这是第2个函数"
return
}
report_home_space () {
echo "这是第3个函数"
return
}
#在这调用一个函数
report_home_space
cat << _EOF_
<HTML>
<HEAD>
<TITLE>$TITLE</TITLE>
</HEAD>
<BODY>
<H1>$TITLE</H1>
<P>$TIME_STAMP</P>
<!-- 在HTML中调用report_uptime函数 -->
report_uptime函数的结果:$(report_uptime)
$(report_disk_space)
$(report_home_space)
</BODY>
</HTML>
_EOF_
3 . 局部变量
这里有一个实例脚本,其说明了怎样来定义和使用局部变量:
#!/bin/bash
# local-vars: script to demonstrate local variables
foo=0 # global variable foo
funct_1 () {
local foo # variable foo local to funct_1
foo=1
echo "funct_1: foo = $foo"
}
funct_2 () {
local foo # variable foo local to funct_2
foo=2
echo "funct_2: foo = $foo"
}
echo "global: foo = $foo"
funct_1
echo "global: foo = $foo"
funct_2
echo "global: foo = $foo"
对两个 shell 函数中的局部变量 foo 赋值,不会影响到在函数之外定义的变量 foo 的值。
有时候我们为了保持命令的输出格式。我们使用一个 here 文档来输出标题和 uptime 命令的输出结果,命令结果被
标签包围,如下:
report_disk_space () {
cat <<- _EOF_
<H2>Disk Space Utilization</H2>
<PRE>$(df -h)</PRE>
_EOF_
return
}
if 分支结构
退出状态
当命令执行完毕后,命令(包括我们编写的脚本和 shell 函数)会给系统发送一个值,叫做退出状态。 这个值是一个 0 到 255 之间的整数,说明命令执行成功或是失败。按照惯例,一个零值说明成功,其它所有值说明失败。 Shell 提供了一个参数,我们可以用它检查退出状态。用具体实例看一下:
ls -d /usr/bin
/usr/bin
echo $?
0
ls -d bin/usr
ls: cannot access /bin/usr: No such file or directory
echo $?
1
shell 提供了两个极其简单的内部命令,它们不做任何事情,除了以一个0或1退出状态来终止执行。 True 命令总是执行成功,而 false 命令总是执行失败:
true
echo $?
false
echo $?
我们能够使用这些命令,来看一下 if 语句是怎样工作的。If 语句真正做的事情是计算命令执行成功或失败:
if true; then echo "It's true."; fi
if false; then echo "It's false."; fi
当 if 之后的命令执行成功的时候,命令 echo “It’s true.” 将会执行,否则此命令不执行。 如果 if 之后跟随一系列命令,则将计算列表中的最后一个命令:
if false; true; then echo "it's true";fi
if true; false; then echo "it's false";fi
测试
1 . 文件表达式
到目前为止,经常与 if 一块使用的命令是 test。这个 test 命令执行各种各样的检查与比较。 它有两种等价模式:
test expression
另一种表达是:
[expression]
这里的 expression 是一个表达式,其执行结果是 true 或者是 false。当表达式为真时,这个 test 命令返回一个零 退出状态,当表达式为假时,test 命令退出状态为1。
这里我们有一个脚本说明了一些文件表达式:
#!/bin/bash
# test-file: Evaluate the status of a file
FILE=~/.bash_profile
if [ -e "$FILE" ]; then
if [ -f "$FILE" ]; then
echo "$FILE is a regular file."
fi
if [ -d "$FILE" ]; then
echo "$FILE is a directory."
fi
if [ -r "$FILE" ]; then
echo "$FILE is readable."
fi
if [ -w "$FILE" ]; then
echo "$FILE is writable."
fi
if [ -x "$FILE" ]; then
echo "$FILE is executable/searchable."
fi
else
echo "$FILE does not exist"
exit 1
fi
exit
这个脚本会计算赋值给常量 FILE 的文件,并显示计算结果。对于此脚本有两点需要注意。第一个, 在表达式中参数
FILE是怎样被引用的。引号并不是必需的,但这是为了防范空参数。如果
F
I
L
E
是
怎
样
被
引
用
的
。
引
号
并
不
是
必
需
的
,
但
这
是
为
了
防
范
空
参
数
。
如
果
FILE的参数展开 是一个空值,就会导致一个错误(操作符将会被解释为非空的字符串而不是操作符)。用引号把参数引起来就 确保了操作符之后总是跟随着一个字符串,即使字符串为空。第二个,注意脚本末尾的 exit 命令。 这个 exit 命令接受一个单独的,可选的参数,其成为脚本的退出状态。当不传递参数时,退出状态默认为零。 以这种方式使用 exit 命令,则允许此脚本提示失败如果 $FILE 展开成一个不存在的文件名。这个 exit 命令 出现在脚本中的最后一行,是一个当一个脚本“运行到最后”(到达文件末尾),不管怎样, 默认情况下它以退出状态零终止。
2 . 测试字符串表达式
警告:当与 test 一块使用的时候, > 和 < 表达式操作符必须用引号引起来(或者是用反斜杠转义)。 如果不这样,它们会被 shell 解释为重定向操作符,造成潜在的破坏结果。 同时也要注意虽然 bash 文档声明排序遵从当前语系的排列规则,但并不这样。将来的 bash 版本,包含 4.0, 使用 ASCII(POSIX)排序规则。
这是一个演示这些问题的脚本:
#!/bin/bash
# test-string: evaluate the value of a string
ANSWER=maybe
if [ -z "$ANSWER" ]; then
echo "There is no answer." >&2
exit 1
fi
if [ "$ANSWER" = "yes" ]; then
echo "The answer is YES."
elif [ "$ANSWER" = "no" ]; then
echo "The answer is NO."
elif [ "$ANSWER" = "maybe" ]; then
echo "The answer is MAYBE."
else
echo "The answer is UNKNOWN."
fi
3 . 整型表达式
这里是一个演示以上表达式用法的脚本:
#!/bin/bash
# test-integer: evaluate the value of an integer.
INT=-5
if [ -z "$INT" ]; then
echo "INT is empty." >&2
exit 1
fi
if [ $INT -eq 0 ]; then
echo "INT is zero."
else
if [ $INT -lt 0 ]; then
echo "INT is negative."
else
echo "INT is positive."
fi
if [ $((INT % 2)) -eq 0 ]; then
echo "INT is even."
else
echo "INT is odd."
fi
fi
这个脚本中有趣的地方是怎样来确定一个整数是偶数还是奇数。通过用模数2对数字执行求模操作, 就是用数字来除以2,并返回余数,从而知道数字是偶数还是奇数。
4 . 更现代的测试版本
这里,类似于 test,expression 是一个表达式,其计算结果为真或假。这个[[ ]]命令非常 相似于 test 命令(它支持所有的表达式),但是增加了一个重要的新的字符串表达式:
string1 =~ regex
其返回值为真,如果 string1匹配扩展的正则表达式 regex。这就为执行比如数据验证等任务提供了许多可能性。 在我们前面的整数表达式示例中,如果常量 INT 包含除了整数之外的任何数据,脚本就会运行失败。这个脚本 需要一种方法来证明此常量包含一个整数。使用 [[ ]] 和 =~ 字符串表达式操作符,我们能够这样来改进脚本:
#!/bin/bash
# test-integer2: evaluate the value of an integer.
INT=-5
if [[ "$INT" =~ ^-?[0-9]+$ ]]; then
if [ $INT -eq 0 ]; then
echo "INT is zero."
else
if [ $INT -lt 0 ]; then
echo "INT is negative."
else
echo "INT is positive."
fi
if [ $((INT % 2)) -eq 0 ]; then
echo "INT is even."
else
echo "INT is odd."
fi
fi
else
echo "INT is not an integer." >&2
exit 1
fi
通过应用正则表达式,我们能够限制 INT 的值只是字符串,其开始于一个可选的减号,随后是一个或多个数字。 这个表达式也消除了空值的可能性。
[[ ]]添加的另一个功能是==操作符支持类型匹配,正如路径名展开所做的那样。例如:
这就使[[ ]]有助于计算文件和路径名。
5 .(( )) - 为整数设计
(( ))被用来执行算术真测试。如果算术计算的结果是非零值,则一个算术真测试值为真。
if ((1)); then echo "It is true"; fi
if ((0)); then echi "It is false"; fi
使用(( )),我们能够略微简化 test-integer2脚本,像这样:
#!/bin/bash
# test-integer2a: evaluate the value of an integer.
INT=-5
if [[ "$INT" =~ ^-?[0-9]+$ ]]; then
if ((INT == 0)); then
echo "INT is zero."
else
if ((INT < 0)); then
echo "INT is negative."
else
echo "INT is positive."
fi
if (( ((INT % 2)) == 0)); then
echo "INT is even."
else
echo "INT is odd."
fi
fi
else
echo "INT is not an integer." >&2
exit 1
fi
6 . 逻辑操作符
这里有一个 AND 操作的示例。下面的脚本决定了一个整数是否属于某个范围内的值:
#!/bin/bash
# test-integer3: determine if an integer is within a
# specified range of values.
MIN_VAL=1
MAX_VAL=100
INT=50
if [[ "$INT" =~ ^-?[0-9]+$ ]]; then
if [[ INT -ge MIN_VAL && INT -le MAX_VAL ]]; then
echo "$INT is within $MIN_VAL to $MAX_VAL."
else
echo "$INT is out of range."
fi
else
echo "INT is not an integer." >&2
exit 1
fi
7 . 控制操作符:分支的另一种方法
bash 支持两种可以执行分支任务的控制操作符。 &&(AND)和||(OR)操作符作用如同 复合命令[[ ]]中的逻辑操作符。这是语法:
command1 && command2
command1 || command2
理解这些操作很重要。对于 && 操作符,先执行 command1,如果并且只有如果 command1 执行成功后, 才会执行 command2。对于 || 操作符,先执行 command1,如果并且只有如果 command1 执行失败后, 才会执行 command2。
在实际中,它意味着我们可以做这样的事情:
mkdir temp && cd temp
这会创建一个名为 temp 的目录,并且若它执行成功后,当前目录会更改为 temp。第二个命令会尝试 执行只有当 mkdir 命令执行成功之后。同样地,一个像这样的命令:
[-d temp] || mkdir temp
会测试目录 temp 是否存在,并且只有测试失败之后,才会创建这个目录。这种构造类型非常有助于在 脚本中处理错误,这个主题我们将会在随后的章节中讨论更多。例如,我们在脚本中可以这样做:
[-d temp] || exit1
如果这个脚本要求目录 temp,且目录不存在,然后脚本会终止,并返回退出状态1。