Shell 脚本基础知识
Unix/Linux上常见的Shell脚本解释器有bash、sh、csh、ksh等,习惯上把它们称作为一种Shell。我们常说有多少中Shell,其实说的是Shell脚本解释器。
几种常见的Shell
**sh** sh是由Steve Bourne 开发,是 Bourne shell 的缩写,sh是Unix标准默认的shell。 **bash** bash是由Brian Fox 和 Chet Ramey共同完成。是Bourne Again Shell的缩写。bash是linux标准默认的shell。 **ash** ash是由Kenneth Almquist编写,linux中占用资源最少的一个小shell,它只包含24个内部命令,因而使用起来不是很方便。 **csh** csh是linux中比较大的内核,它由以William Joy为代表的共计47位作者编成,共有52个内部命令。该shell其实是指向/bin/tcsh这样的一个shell,就是说csh就是tcsh。 **ksh** ksh是由Eric Gisin编写,是Korn Shell的缩写,共有42条内部命令。该shell最大的优点是几乎和商业发行版的ksh完全兼容。这样就可以在不用花钱购买商业版本的情况下尝试商业版本的性能了。 **注意:bash是linux默认的shell,它基于Bourne Shell,吸收了csh和ksh的一些特性,bash完全兼容sh,就是说,用sh写的脚本可以不加修改的在bash中执行**
第一个Shll脚本
$ vi hello.sh #新建一个shell脚本(扩展名为sh的文件,sh代表shell,扩展名并不影响脚本的执行。也可以直接起名hello)
在脚本中输入以下代码:
#!/bin/bash # "#!"是一个约定的标记,它告诉系统需要使用哪一种Shell。 echo "Hello World!"
运行Shell的方法:
$ chmod +x hello.sh #给文件增加执行权限 $ ./hello.sh #执行脚本 $ /bin/sh hello.sh #以sh运行脚本 $ /bin/bash hello.sh #以bash运行脚本
示例:
编写一个脚本,从标准输入(stdin)中读取名字,显示在标准输出(stdout)上。
#/bin/bash echo "What's your name?" read NAME echo "Hello ${NAME}"
Shell 变量
定义变量
变量名与等号直接不能有空格。变量明的命名规则需遵循如下规则:
1、首个字符必须为字母(a-z,A-Z)
2、中间不能有空格,可以使用下划线(_)
3、不能使用标点符号
4、不能使用shell里的关键字(在命令行中使用help命令可以查看保留关键字)
变量定义示例:
variableName="value"
使用变量
使用一个定义过的变量,只要在变量名前面加 $ 符号就可以了。如:
variableName="value" echo $variableName
有些时候需要在变量名外面加上花括号帮助解释器识别变量的边界,如下面这种情况
SKILL=Ada echo "I'm a good at ${SKILL}Script"
重新定义变量
已经定义的变量,可以被重新定义,如:
#!/bin/bash NAME=Dave echo "Hello ${NAME}" NAME=Abby echo "Hello ${NAME}"
只读变量
使用readonly命令可以将变量定义为只读变量,只读变量的值不能改变
#!/bin/bash NAME=Dave readonly NAME NAME=Abby
运行脚本会报错,结果如下
./test.sh: line 5: NAME: readonly variable
删除变量
使用unset命令删除变量,变量被删除后不能再次使用;unset命令不能删除只读变量
示例:
#!/bin/bash NAME=Dave unset NAME echo $NAME
运行结果不会有任何输出。
Shell特殊变量
实例
#!/bin/bash echo "File Name : $0" echo "First Parameter : $1" echo "Second Parameter : $2" echo "All Parameter : $@" echo "All Parameter : $*" echo "Total Number of Parameter $#" echo "The Shell of the process ID is : $$"
运行结果:
$ ./test.sh Dave Abby File Name : ./test.sh First Parameter : Dave Second Parameter : Abby All Parameter : Dave Abby All Parameter : Dave Abby Total Number of Parameter 2 The Shell of the process ID is : 2752 $ echo $? #查看./test.sh 退出状态。一般情况下成功返回0,失败返回-1 0
* $* 和 $@的区别 *
很多关于shell的书本上写当它们被双引号包含时,$* 会将所有参数作为一个整体,而$@ 会将各个参数分开。但是,我在运行脚本的时候并没有发现这样的情况。我是在Ubuntu1204版本中测试的。代码如下
#!/bin/bash echo '$*='"$*" echo '$@='"$@"
Shell替换
命令替换
命令替换是指shell可以先执行命令,将输出结果暂时保存,在适当的地方输出
示例:
#!/bin/bash DATE=`date` echo "$DATE"
变量替换
示例:
#!/bin/bash echo ${var:-"Hello"} echo $var echo ${var:="Hello"} echo $var echo ${var:+"World"} echo $var unset var echo ${var:?"message"} echo $var
结果如下:
$ ./test.sh Hello Hello Hello World Hello ./test.sh: line 13: var: message
Shell的if语句
if语句通过关系运算符判断表达式的真假来决定执行那个分支,Shell有三种if语句。
- if … fi 语句
- if … else … fi 语句
- if … elif … else … fi 语句
if … fi 语句的语法
if [ expression ] then Statement(s) to be executed if expression is true fi
**注意:**expression 和方括号之间必须有空格。否则会有语法错误
示例:
#!/bin/bash a=10 b=20 if [ $a == $b ] then echo "a == b" fi if [ $a != $b ] then echo "a! = b" fi
if … else … fi语句语法
if [ expression ] then Statement(s) to be executed if expression is true else Statement(s) to be executed if expression is not true fi
示例:
#!/bin/bash a=10 b=20 if [ $a == $b ] then echo "a == b" else echo "a! = b" fi
if … elif …fi语句语法
if [ expression 1 ] then Statement(s) to be executed if expression 1 is true elif [ expression 2 ] then Statement(s) to be executed if expression 2 is true elif [ expression 3 ] then Statement(s) to be executed if expression 3 is true else Statements to be executed if expression not is true fi
示例:
#!/bin/bash a=10 b=20 if [ $a == $b ] then echo "a == b" elif [ $a -gt $b ] then echo "a > b" elif [ $a -lt $b ] then echo "a < b" else echo "None of the condition met" fi
Shell运算符
bash支持很多运算符。包括算数运算符、关系运算符、布尔运算符、字符串运算符和文件测试运算符。
算数运算符
bash中实现数学运算的语法。
- 使用expr表达式计算工具。 expr 1 + 2
- [1+2]− ((1+2))
使用expr时需要注意:
- 表达式和运算符之间要有空格。
- 完整的表达式要被“包含起来。
示例:
#!/bin/bash a=10 b=20 echo "`expr $a + $b`" echo $[$a+$b] echo $((a+b)) echo "`expr $a - $b`" echo "`expr $a \* $b`" # *号需要转义 echo $[$a*$b] echo "`expr $a / $b`" echo "`expr $a % $b`"
关系运算符
关系运算符只支持数字,不支持字符串。除非字符串的值是数字。
示例:
#!/bin/bash a=10 b=20 if [ $a -eq $b ] then echo "a == b" else echo "a != b" fi if [ $a -ne $b ] then echo "a != b" else echo "a == b" fi if [ $a -gt $b ] then echo "a > b" else echo "a < b" fi if [ $a -lt $b ] then echo "a < b" else echo "a > b" fi if [ $a -ge $b ];then echo "a > b";else echo "a < b";fi if [ $a -le $b ];then echo "a < b";else echo "a > b";fi
布尔运算符
示例:
#!/bin/bash a=10 b=20 if [ ! $a -eq $b ]; then echo "a == b"; else echo "a != b"; fi if [ $a -lt $b -o $b -gt $a ]; then echo "a < b"; else echo "a > b"; fi if [ $a -le $b -a $b -ge $a ]; then echo "a < b"; else echo "a > b"; fi
字符串运算符
示例:
#!/bin/bash a="abc" b="edf" if [ ! $a = $b ]; then echo "a != b"; else echo "a == b"; fi if [ $a != $b ]; then echo "a != b"; else echo "a == b"; fi if [ -z $a -o -z $b ]; then echo "string length isn't zero"; else echo "string length is zero"; fi if [ -n $a -a -n $b ]; then echo "string length is zero" else echo "string length isn't zero"; fi if [ $a -a $b ];then echo "string length is zero" else echo "string length isn't zero"; fi
文件测试运算符
文件测试运算符用于检测文件的各种属性
示例:
#!/bin/bash if [ -b $1 ]; then echo "$1 is block file"; else echo "$1 is not block file"; fi if [ -c $1 ]; then echo "$1 is str file"; else echo "$1 is not str file"; fi if [ -d $1 ]; then echo "$1 is directory file"; else echo "$1 is not directory file"; fi if [ -f $1 ]; then echo "$1 is ordinary file"; else echo "$1 is not ordinary file"; fi if [ -g $1 ]; then echo "$1 SGID bit"; else echo "$1 not SGID bit"; fi if [ -k $1 ]; then echo "$1 Sticky bit"; else echo "$1 not Sticky not bit"; fi if [ -p $1 ]; then echo "$1 is pipe file"; else echo "$1 is not pipe file"; fi if [ -u $1 ]; then echo "$1 SUID bit"; else echo "$1 not SUID bit"; fi if [ -r $1 ]; then echo "$1 is read file"; else echo "$1 is not read file"; fi if [ -w $1 ]; then echo "$1 is write file"; else echo "$1 is not write file"; fi if [ -x $1 ]; then echo "$1 is execute file"; else echo "$1 is not execute file"; fi if [ -s $1 ]; then echo "$1 is not zero"; else echo "$1 is zero"; fi if [ -e $1 ]; then echo "$1 exists"; else echo "$1 not exists"; fi
运行结果: