变量
在shell里,使用变量之前不需要事先为它们做出声明,只是通过使用它们来创建它们。在默认情况下,所有变量都被当做字符串并以字符串来存储,即使它们被赋值为数值时也是如此。
在shell中,可以通过在变量名前加一个$符号来访问它的内容。想要获取变量内容,必须在它前面加上一个$字符。当为变量赋值时,只需要使用变量,该变量会根据需要自动创建。一种检查变量内容的简单方式是在变量名前加上一个$符号,再用echo命令将它的内容输出到终端上。例如:
$ a=bye
$ echo $a
bye
$ a="hello world"
$ echo $a
hello world
$ a=1+1
$ echo
1+1
使用引号
如果字符串里包含空格,必须用引用把它们括起来,此外,等号两边不能有空格。
可以使用read命令将用户的输入赋值给一个变量。通常情况下,在用户按下回车键时,read命令结束。当从终端上读取一个变量名时,一般不需要使用引号。
一般情况下,脚本文件中的参数以空白符分隔(空格,制表符,换行符),就必须给参数加上引号。
如果把一个$变量表达式放在双引号中,程序执行到这一行时就会把变量替换为它的值;如果把它放在单引号中,就不会替换。还可以通过在$前面加上一个\字符以取消它的特殊含义。
环境变量
当一个shell脚本程序开始执行时,一些变量会根据环境设置中的值进行初始化。这些变量通常用大写字母做名字,以便把它们和用户在脚本程序里定义的变量区分开来,后者按照惯例都用小写字母做名字。
$HOME | 当前用户的家目录 |
$PATH | 以冒号分隔的用来搜索命令的目录列表 |
$PS1 | 命令提示符 |
$PS2 | 二级提示符 |
$IFS | 输入域分隔符 |
$0 | shell脚本的名字 |
$# | 传递给脚本的参数个数 |
$$ | shell脚本的进程号,脚本程序通常会用它来生成唯一的临时文件,如/tmp/tmpefile_$ $ |
可以通过执行env <command>命令来查看程序在不同环境下是如何工作。
参数变量
如果脚本程序在调用时带有参数,一些额外的变量就会被创建。即使没有传递任何参数,环境变量$#也依然存在,只不过它的值是0。
$1,$2... | 脚本程序的参数 |
$* | 在一个变量中列出所有的参数,各个参数之间用环境变量IFS中的第一个分隔符分开 |
$@ | 即使IFS为空,参数也不会挤在一起 |
双引号里面的$@把各个参数扩展为彼此分开的域,而不受IFS值的影响。一般来说,如果你想访问脚本程序的参数,使用$@是明智的选择。
#!/bin/sh
i="hello"
echo $i
echo "The program $0 is now running"
echo "The second parameter was $2"
echo "The first parameter was $1"
echo "The parameter list was $*"
echo "THe user's home directory is $HOME"
echo "Please enter a new greeting"
read i
echo $i
echo "The script is now complete"
exit 0
其中$0是shell脚本的名字,$1,$2是脚本程序的参数,$*在一个变量中列出所有的参数。
条件
所有程序设计语言的基础都是对条件的进行测试判断,并根据不同测试结果采取不同行动。
一个shell脚本能够对任何可以从命令行上调用的命令的退出码进行测试,其中也包括自己编写的脚本程序。这也就是要在所有自己编写的脚本程序的结尾包括一条返回值的命令的重要原因。
test或[命令
大多数脚本程序都会广泛使用shell的布尔判断命令[或test
注意必须在[符号和被检查的条件之间留出空格。如果把then和if放在同一行上,则需要使用一个分号把test语句和then分隔开。
test命令可以使用的条件类型可以分为3类:字符串比较,算术比较和与文件有关的条件测试。
字符串比较 | 结果 |
string1 = string2 | 如果两个字符串相同,则结果为真 |
string1 != string2 | 如果两个字符串不同,则结果为真 |
-n string | 如果字符串不为空,则结果为真 |
-z string | 如果字符串为null,则结构为真 |
算术比较 | 结果 |
expres1 -ep expres2 | 如果两个表达式相等,则结果为真 |
expres1 -ne expres2 | 如果两个表达式不等,则结果为真 |
expres1 -gt expres2 | 如果expres1大于expres2,则结果为真 |
expres1 -ge expres2 | 如果expres1大于等于expres2,则结果为真 |
expres1 -lt expres2 | 如果expres1小于 |
expres1 -le expres2 | 如果expres1小于等于 |
! expres | 如果expres为假,则结果为真 |
文件条件测试 | 结果 |
-d file | 如果文件是一个目录,则结果为真 |
-e file | 如果文件存在,则结果为真(通常使用-f) |
-f file | 如果文件是一个普通文件,则结果为真 |
-g file | 如果文件的set-group-id位被设置,则结果为真 |
-r file | 如果文件可读,则结果为真 |
-s file | 如果文件的大小不为0,则结果为真 |
-u file | 如果文件的set-user-id位被设置,则结果为真 |
-w file | 如果文件可写,则结果为真 |
-x file | 如果文件可执行,则结果为真 |
控制结构
shell有一组控制结构,它们与其他程序设计语言中的控制结构类似。
if语句
if conditon
then
statement
else
statement
fi
判断条件时,注意给变量加上引号,这样一个空变量提供的就是合法测试了。
for语句
for variable in values
do
statement
done
while语句
因为在默认情况下,所有的shell变量值都被认为是字符串,所以for循环特别适合对于一系列字符串进行循环处理,但如果事先并不知道循环要执行的次数,那么使用while。
while condition
do
statement
done
until语句
until condition
do
statement
done
case语句
case variable in
pattern [ | pattern] ...) statement;;
pattern [ | pattern] ...) statement;;
esac
命令列表
有时需要将多条命令连接成一个序列。
AND列表
AND列表结构:只有在前面所有的命令都执行成功的情况下才执行后一条命令。
statement1 && statement2 && statement3 && ...
从左向右执行每一条命令,&&的作用是检查前一条命令的返回值是否为true。
OR列表
OR列表结构允许我们持续执行一系列命令直到有一条命令成功为止,其后的命令将不再被执行。
statement1 || statement2 || statement3 || ...
从左开始执行每条语句,如果一条命令返回的是false,它右边的下一条命令才能被执行。
函数
要定义一个shell函数,只需要写出它的名字,然后是一对空括号,再把函数中的语句放在一对花括号中,如下所示:
function_name(){
statement
}