原文地址:http://linuxhelp.blogspot.com/2005/10/10-seconds-guide-to-bash-shell.html
october 23, 2005
首先要澄清的是,这里不是要对shell 脚本编程作详细的研究,正如本文标题所指出的,这是一篇介绍bash shell 脚本编写语法的快速指南。如果你想深入研究,那么建议你买一本关于shell脚本编程的书 ;-) 。好,现在开始我们的学习,开始用停表计时吧!
正文:
常见的环境变量:
$PATH - 为可执行程序设置查找路径,与msdos下的$PATH 变量类似。
$HOME - 用户的本地目录(home).
$MAIL - 保存用户设置的mail投递路径。
保存了一串 在命令行中用于 字符分隔 的字符 组成的字串。这个字串通常包含了空格,制表符,换行符。要查看之,你要做一个octal dump 的操作 如下:
$ echo $IFS | od -bc
PS1 and PS2 - 第一顺序提示符和第二顺序提示符(Primary and secondary prompts). PS1 默认设为 $ , PS2 设置为 '>' . 查看PS2可以通过如下命令:$ ls |
然后按回车。
$USER - 用户登陆名。
$TERM - 终端类型标识。有时必须为编辑器设置正确的终端标识,以便其正常工作。
$SHELL - 登陆时可通过此查看shell 的类型.
注意:要查看以上变量的值,只要简单地用 echo 命令 加 $变量名就行了。例如:
$ echo $USER
ravi
就得到了$USER 的值。
bash shell 编程规则
1) 编写的脚本首行必须为:#!/bin/bash
#井号,后跟!叹号,接着是shell的路径。这个语句能够告诉解析器这是一个shell脚本,同时指定shell的路径。
2)执行脚本前,先为脚本赋执行权限:
$ chmod ugo+x your_shell_script.sh
3)把脚本以.sh后缀命名。这让人知道这是一个shell脚本。这不是必须的,但是这是规范,没错,规范。
条件语句
if
if 语句-对条件命令进行判断然后决定流程的执行。
蓝色的字必要的。红色的则是可选的。
语法:
if condition_is_true
then
execute commands
else
execute commands
fi
if 条件可以是多路选择(分支结构)。这样可以对多条件进行判断。if condition_is_true
then
execute commands
elif another_condition_is_true
then
execute commands
else
execute commands
fi
例子:
if grep "linuxhelp" thisfile.html
then
echo "Found the word in the file"
else
echo "Sorry no luck!"
fi
if 的搭档- test命令
test 是shell的一个内置命令。test对右边的操作数进行判断。返回true或false.为此,test 用特定的操作符来作条件判断,如下所示:
关系型操作符-eq Equal to等于
-lt Less than小于
-gt Greater than大于
-ge Greater than or equal to大于等于
-lt Less than小于
-le Less than or equal to 小于等于
文件相关的测试:-f file 存在且为常规文件,则为真
-r file 文件存在且可读,则为真
-w file 文件存在且可写,则为真
-x file 文件存在且可执行,则为真
-d file 为文件夹,则为真
-s file 文件存在且不为零则为真
字符串测试:-n str True if string str is not a null string
-z str True if string str is a null string
str1 == str2 True if both strings are equal
str1 != str2 True if both strings are unequal
str True if string str is assigned a value
and is not null.
上面的意思是:
-n str 如果str非空则为真
-z str 如果str为空则为真
str1 == str2 如果两个字串相等则为真
str1 != str2 如果两个字串不等则为真
str 如果str有赋非空值则为真。
test 函数 也允许在一行中同时检验多个表达式。
-a Performs the AND function
-o Performs the OR function
举例:test $d -eq 25 ; echo $d
上面的意思是:如果$d变量的值等于25,则输出这个值。
test $s -lt 50; do_something
if [ $d -eq 25 ]
then
echo $d
fi
在上面的例子中,我用中括号标记的,由test 处理,其实,用如下的方式也可以处理:
if [ $str1 == $str2 ]
then
do something
fi
if [ -n "$str1" -a -n "$str2" ]
then
echo 'Both $str1 and $str2 are not null'
fi
上面的意思是:如果两个字串都不为null ,就执行 echo 命令。
用test时的注意事项:
如果你用[ ] 替代test,那么请在]前和[后加上空格,否则将不能解析。
注意:test的操作数限制为整数,小数将会被自动截断。
不要用通配符来检查字符串的匹配性。在shell 中,通配符用来匹配目录中有共同名称的的文件名,而不用于test命令。
case 语句
case 是shell 提供的另一个作为条件判断的语句。
语法:case expression in
pattern1) execute commands ;;
pattern2) execute commands ;;
...
esac
The keywords here are in, case and esac. The ';;' is used as option terminators. The construct also uses ')' to delimit the pattern from the action.
语法中有case,in和esac三个关键字。
符号;; 是各个选项的结尾标记。
而右括号)用于分割pattern和动作。
Example:...
echo "Enter your option : "
read i;
case $i in
1) ls -l ;;
2) ps -aux ;;
3) date ;;
4) who ;;
5) exit
esac
注:最后一个选项是不需要;;作结的,当然你喜欢,也可以加上。
另一个例子:case `date |cut -d" " -f1` in
Mon) commands ;;
Tue) commands ;;
Wed) commands ;;
...
esac
case 可以匹配一个以上的模式(pattern),你可以用通配符来匹配模式;...
echo "Do you wish to continue? (y/n)"
read ans
case $ans in
Y|y) ;;
[Yy][Ee][Ss]) ;;
N|n) exit ;;
[Nn][Oo]) exit ;;
*) echo "Invalid command"
esac
在以上的例子中,如果你输入 YeS, YES,yEs 或者任何其他的组合,都可以被匹配到。
到此,条件语句的介绍告一段落。
循环语句
while 循环
语法:while condition_is_true
do
execute commands
done
举例:while [ $num -gt 100 ]
do
sleep 5
done
while :
do
execute some commands
done
以上代码将会执行一个无限的循环,当然你可以使用while true来代替while : 。
在此我将会介绍和循环相关的关键字:break和continue.
break - 这个关键字能够退出循环,终止执行。
continue - 这个关键字可以暂停当前循环中跟在其后的语句的执行,转而执行下一个循环。
until 循环
如果until 后的条件为false,那么就一直循环地执行do 中的命令。until false
do
execute commands
done
...
until [ -r myfile ]
do
sleep 5
done
The above code is executed repeatedly until the file myfile can be read.
以上代码将会重复执行,直到myfile是可读的。
for 循环
语法:for variable in list
do
execute commands
done
举例:...
for x in 1 2 3 4 5
do
echo "The value of x is $x";
done
上面例子中,列举了1-5五个数。
下面是另一个例子:for var in $PATH $MAIL $HOME
do
echo $var
done
如果你有一个文件夹,里面都是要编译的*.java文件
那么你可以写一个这样的shell脚本:...
注意:如上面的例子所示,脚本里是可以用通配符的。
for file in *.java
do
javac $file
done
写shell脚本是的一些特殊符号和含义:$* - This denotes all the parameters passed to the script
at the time of its execution. Which includes $1, $2
and so on.
$0 - Name of the shell script being executed.
$# - Number of arguments specified in the command line.
$? - Exit status of the last command.
以上的符号我们称之为位置参数。让我通过如下的例子来解析位置参数的用法。
假设我有一个脚本my_script.sh,并执行如下:
$ ./my_script.sh linux is a robust OS
如上所示,我给脚本传递了5个参数。在此,位置参数的取值为:
$* - 的取值包含了'linux','is','a','robust','OS'.
$0 - 的取值是my_script.sh -所执行的脚本文件的名称。
$# - 取值为5-参数的个数。
$$ - 取值为当前进程的id.你可以在执行脚本时为所创建的临时文件(如果有)
用这个参数来命名以得到一个唯一的名称。
$1 - 第一个参数的值 ,即 'linux'
$2 - 第一个参数的值 ,即 'is'
...等等。
set 和 shift 语句
set - 为位置参数关联一个取值。
例如:$ set `date`
$ echo $1
$ echo $*
$ echo $#
$ echo $2
shift - 把位置参数的值直接转移给下一个参数(编号小一级的位置参数)。
每执行一次shift,就转移一次。
举例:$ set `date`
$ echo $1 $2 $3
$ shift
$ echo $1 $2 $3
$ shift
$ echo $1 $2 $3
查看当前shell脚本执行的进程id,可以用:$ echo $$
2667
并可以用如下脚本验证:$ ps -f |grep bash
read 语句
read 可以使得你的shell 脚本实现人机交互。
使用read 语句可以让用户在执行shell的时候设定变量的值。
当脚本执行到read语句时,将会暂停而等待用户用键盘输入变量值,
读入值后,shell程序继续执行。
例如:#!/bin/sh
echo "Enter your name : "
read name
echo "Hello $name , Have a nice day."
退出状态/返回值
Exit status of the last command
每一个命令执行完之后都会有一个值被返回。这个值叫做退出状态或者返回值。如果命令被成功执行,将会返回true,否则返回false.这可以通过使用位置参数$?来检查。
本文中,对bash shell 的脚本编写做了简明的介绍,但是其实还有更多的shell编程知识没有谈及。对我们而言,shell 有几种,bash shell 只是其中之一。每种shell在语法上都有少许的差异。比如c shell,其语法有和c语言很相似。而在这里介绍的内容对于各种shell都适用。