Shell 脚本基础知识

来源:互联网 发布:命令与征服 知乎 编辑:程序博客网 时间:2024/04/27 01:49

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/bashecho "What's your name?"read NAMEecho "Hello ${NAME}"

Shell 变量

定义变量
变量名与等号直接不能有空格。变量明的命名规则需遵循如下规则:
1、首个字符必须为字母(a-z,A-Z)
2、中间不能有空格,可以使用下划线(_)
3、不能使用标点符号
4、不能使用shell里的关键字(在命令行中使用help命令可以查看保留关键字)

变量定义示例:

variableName="value"

使用变量
使用一个定义过的变量,只要在变量名前面加 $ 符号就可以了。如:

variableName="value"echo $variableName

有些时候需要在变量名外面加上花括号帮助解释器识别变量的边界,如下面这种情况

SKILL=Adaecho "I'm a good at ${SKILL}Script"

重新定义变量
已经定义的变量,可以被重新定义,如:

#!/bin/bashNAME=Daveecho "Hello ${NAME}"NAME=Abbyecho "Hello ${NAME}"

只读变量
使用readonly命令可以将变量定义为只读变量,只读变量的值不能改变

#!/bin/bashNAME=Davereadonly NAMENAME=Abby

运行脚本会报错,结果如下

./test.sh: line 5: NAME: readonly variable

删除变量
使用unset命令删除变量,变量被删除后不能再次使用;unset命令不能删除只读变量
示例:

#!/bin/bashNAME=Daveunset NAMEecho $NAME

运行结果不会有任何输出。

Shell特殊变量

特殊变量列表
实例

#!/bin/bashecho "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 AbbyFile Name : ./test.shFirst Parameter : DaveSecond Parameter : AbbyAll Parameter : Dave AbbyAll Parameter : Dave AbbyTotal Number of Parameter 2The Shell of the process ID is : 2752$ echo $?     #查看./test.sh 退出状态。一般情况下成功返回0,失败返回-10

* $* 和 $@的区别 *
很多关于shell的书本上写当它们被双引号包含时,$* 会将所有参数作为一个整体,而$@ 会将各个参数分开。但是,我在运行脚本的时候并没有发现这样的情况。我是在Ubuntu1204版本中测试的。代码如下

#!/bin/bashecho '$*='"$*"echo '$@='"$@"

Shell替换

命令替换
命令替换是指shell可以先执行命令,将输出结果暂时保存,在适当的地方输出
示例:

#!/bin/bashDATE=`date`echo "$DATE"

变量替换
变量替换表
示例:

#!/bin/bashecho ${var:-"Hello"}echo $varecho ${var:="Hello"}echo $varecho ${var:+"World"}echo $varunset varecho ${var:?"message"}echo $var

结果如下:

$ ./test.sh HelloHelloHelloWorldHello./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 truefi

**注意:**expression 和方括号之间必须有空格。否则会有语法错误
示例:

#!/bin/basha=10b=20if [ $a == $b ]then        echo "a == b"fiif [ $a != $b ]then        echo "a! = b"fi

if … else … fi语句语法

if [ expression ]then    Statement(s) to be executed if expression is trueelse    Statement(s) to be executed if expression is not truefi

示例:

#!/bin/basha=10b=20if [ $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 trueelif [ expression 2 ]then    Statement(s) to be executed if expression 2 is trueelif [ expression 3 ]then    Statement(s) to be executed if expression  3 is trueelse    Statements to be executed if expression not is truefi  

示例:

#!/bin/basha=10b=20if [ $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/basha=10b=20echo "`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/basha=10b=20if [ $a -eq $b ]then        echo "a == b"else        echo "a != b"fiif [ $a -ne $b ]then        echo "a != b"else        echo "a == b"fiif [ $a -gt $b ]then        echo "a > b"else        echo "a < b"fiif [ $a -lt $b ]then        echo "a < b"else        echo "a > b"fiif [ $a -ge $b ];then echo "a > b";else echo "a < b";fiif [ $a -le $b ];then echo "a < b";else echo "a > b";fi

布尔运算符
布尔运算符列表
示例:

#!/bin/basha=10b=20if [ ! $a -eq $b ]; then echo "a == b"; else echo "a != b"; fiif [ $a -lt $b -o $b -gt $a ]; then echo "a < b"; else echo "a > b"; fiif [ $a -le $b -a $b -ge $a ]; then echo "a < b"; else echo "a > b"; fi

字符串运算符
字符串运算符列表
示例:

#!/bin/basha="abc"b="edf"if [ ! $a = $b ]; then echo "a != b"; else echo "a == b"; fiif [ $a != $b ]; then echo "a != b"; else echo "a == b"; fiif [ -z $a -o -z $b ]; then echo "string length is zero";        else echo "string length isn't zero"; fiif [ -n $a -a -n $b ]; then echo "string length isn't zero"        else echo "string length is zero"; fiif [ $a -a $b ];then echo "string length isn't zero"        else echo "string length is zero"; fi

文件测试运算符
文件测试运算符用于检测文件的各种属性
文件测试运算符列表
示例:

#!/bin/bashif [ -b $1 ]; then echo "$1 is block file"; else echo "$1 is not block file"; fiif [ -c $1 ]; then echo "$1 is str file"; else echo "$1 is not str file"; fiif [ -d $1 ]; then echo "$1 is directory file"; else echo "$1 is not directory file"; fiif [ -f $1 ]; then echo "$1 is ordinary file"; else echo "$1 is not ordinary file"; fiif [ -g $1 ]; then echo "$1 SGID bit"; else echo "$1 not SGID bit"; fiif [ -k $1 ]; then echo "$1 Sticky bit"; else echo "$1 not Sticky not bit"; fiif [ -p $1 ]; then echo "$1 is pipe file"; else echo "$1 is not pipe file"; fiif [ -u $1 ]; then echo "$1 SUID bit"; else echo "$1 not SUID bit"; fiif [ -r $1 ]; then echo "$1 is read file"; else echo "$1 is not read file"; fiif [ -w $1 ]; then echo "$1 is write file"; else echo "$1 is not write file"; fiif [ -x $1 ]; then echo "$1 is execute file"; else echo "$1 is not execute file"; fiif [ -s $1 ]; then echo "$1 is not zero"; else echo "$1 is  zero"; fiif [ -e $1 ]; then echo "$1 exists"; else echo "$1 not exists"; fi

运行结果:

$ ./test.sh  test.shtest.sh is not block filetest.sh is not str filetest.sh is not directory filetest.sh is ordinary filetest.sh not SGID bittest.sh not Sticky not bittest.sh is not pipe filetest.sh not SUID bittest.sh is read filetest.sh is write filetest.sh is execute filetest.sh is not zerotest.sh exists[关于SUID,SGID,Sticky的属性请参考:](http://blog.csdn.net/u011641885/article/details/45442053)

Shell中的字符串

Shell中的字符串可以用双引号,也可以用单引号,也可以不用引号。如:

#!/bin/basha="abc"b=edfc='hij'echo $aecho $becho $c

双引号与单引号的区别
单引号:单引号中的任何字符都会原样输出,单引号中的变量是无效的。单引号中不能出现单引号。
双引号:双引号中可以有变量,双引号中可以出现转义字符。
示例:

#!/bin/basha="abc"b=edfecho "$a"echo '$b'

运行结果如下:

$ ./test1.sh abc$b

字符串的几种用法

#!/bin/basha="abc"b=edfecho "$a"$b""####**字符串的拼接**  输出结果是abcedf
#!/bin/basha="abc"echo ${#a}####**获取字符串的长度** 
#!/bin/basha="abc"echo ${a:1:2}####**提取字符串**   输入结果是bc
#!/bin/basha="hello world"echo `expr index "$a" d`   ##在字符串$a中查找字符d第一次出现的位子####**查找字符或字符串**  

Shell中的数组

定义数组
bash支持一维数组(不支持多维数组),并且没有限定数组的大小。数组元素的下标由0开始编号,获取数组中的元素要利用下标,下标跨越式整数或者算术表达式,其值应大于或等于0。

数组的定义有3种方式

array_name=("hello" "world")  #各元素直接用空格隔开array_name=(helloworld)    #各元素直接用换行隔开c[0]=helloc[2]=world   #单独定义数组的各个元素

数组的读取格式
读取数组元素值的一般格式是:

 ${array_name[index]}

示例:

#!/bin/basha=("hello" "world")b=(helloworld)c[0]=helloc[2]=worldecho "${a[0]} ${a[1]}"echo "${b[0]} ${b[1]}"echo "${c[0]} ${c[2]}"echo "${a[@]}"   # @代表取得数组中所有元素echo "${b[*]}"   # *代表取得数组中的所有元素echo "${#a[@]}"  #  获取数组的元素个数echo "${#a[0]}"  #  获取数组中单个元素的长度

Shell的分支语句

case … esac 是shell的分支语句,匹配一个值或一个模式,如果匹配成功,执行相匹配的命令,case语句格式如下:

casein模式1)    command1    command2    command3    ;;模式2)    command1    command2    command3    ;;*)    command1    command2    command3    ;;esac

case工作方式如上所示。取值后面必须为关键字 in ,每一模式必须以右括号结束。取值可以为变量或者常数。匹配发现取值符合某一模式后,其间所有命令开始执行直至 ;;。(;; 类似C语言的break)
取值将检测匹配的每一个模式,一旦模式匹配,则执行完匹配模式相应的内容后不再继续其他模式。如果无一匹配模式,使用 * 捕获该值。在执行相对应内容。

示例:

#!/bin/bashcase $1 in-f)        echo "FILE"        ;;-d)        echo "DIR"        ;;*)        echo "NONE"        ;;esac

运行结果:

$ ./test.sh -fFILE$ ./test.sh -dDIR$ ./test.sh NONE$ ./test.sh -gNONE

Shell循环

Shell中for循环
for循环一般格式为

for 变量 in 列表do    command1    command2    .....done

列表是一组值(数组、字符串等)组成的序列,每个值通过空格分隔。每循环一次,就将列表中的下一个值赋给变量。

#!/bin/bashfor loop in  `date`do        echo $loopdone

运行结果:

$ ./test.sh 六5222:32:38HKT2015

Shell中while循环
while循环格式

while commanddo    Statement(s) to be executed if command is truedone##command  一般为测试条件,当条件为真是执行

示例:

#!/bin/bashwhile read VALUEdo        echo $VALUEdone##从标准输入中读取字符串

Shell中until循环
until循环的格式为:

until commanddo    Statement(s) to be executed if command is falsedone

command 一般为条件表达式,如果返回值为false,则继续执行循环语句,否则跳出循环。
示例:

#!/bin/basha=0until [ ! $a -lt 10 ]do        echo $a        a=$[$a+1]done#输出数字0-9

循环中可以使用break关键字和continue关键字跳出循环,用法如C程序中的break和continue

Shell中的函数

Shell函数的定义格式如下:

function function_name (){    list of commands    [return value]}##关键字function 可以省略。##函数的返回值只能是整数,一般用来表示函数是否执行成功。##如果不加return语句,会将最后一条命令运行结果作为返回值。##使用 $? 接收函数返回值

函数的参数:
调用函数的时可以向其传递参数。在函数体内部。通过nn10,{11}。

函数的调用:
函数的调用只需要给出函数名即可。不需要加括号。
如果希望直接从终端调用函数,可以将函数定义在主目录下的 .profile 文件中。这样每次登陆后,在命令提示符后面输入函数名字就可以直接调用
函数可以使用unset命令删除

unset .f function_name  #一定要在函数名前加上 .f 参数

示例:

#!/bin/bashfun (){        echo $1        echo $2        return $(($1+$2))}fun $1 $2   #调用函数,传递参数,这里的$1和$2是shell脚本的参数ret=$?     #接收函数的返回值echo "The sum of two numbers is $ret"

运行结果:

 ./test1.sh 10 201020The sum of two numbers is 30

Shell文件包含

shll可以将外部脚本的内容合并到当前脚本
shell中包含脚本格式

. filename

或者

source filename

注意:被包含的脚本不需要执行权限也可以执行。
示例:

#!/bin/bash. ./test1.sh $1 $2echo test1.sh run over

执行结果:

$ ll test1.sh -rw-rw-r-- 1 gino gino 121 52 23:46 test1.sh$ cat test1.sh #!/bin/bashfun (){    echo $1    echo $2    return $(($1+$2))    }fun $1 $2ret=$?echo "The sum of two numbers is $ret"$ ./test2.sh 1 212The sum of two numbers is 3test1.sh run
1 0
原创粉丝点击