Shell 脚本基础知识
2015-05-01 21:58
549 查看
Unix/Linux上常见的Shell脚本解释器有bash、sh、csh、ksh等,习惯上把它们称作为一种Shell。我们常说有多少中Shell,其实说的是Shell脚本解释器。
在脚本中输入以下代码:
运行Shell的方法:
示例:
编写一个脚本,从标准输入(stdin)中读取名字,显示在标准输出(stdout)上。
变量名与等号直接不能有空格。变量明的命名规则需遵循如下规则:
1、首个字符必须为字母(a-z,A-Z)
2、中间不能有空格,可以使用下划线(_)
3、不能使用标点符号
4、不能使用shell里的关键字(在命令行中使用help命令可以查看保留关键字)
变量定义示例:
使用变量
使用一个定义过的变量,只要在变量名前面加 $ 符号就可以了。如:
有些时候需要在变量名外面加上花括号帮助解释器识别变量的边界,如下面这种情况
重新定义变量
已经定义的变量,可以被重新定义,如:
只读变量
使用readonly命令可以将变量定义为只读变量,只读变量的值不能改变
运行脚本会报错,结果如下
删除变量
使用unset命令删除变量,变量被删除后不能再次使用;unset命令不能删除只读变量
示例:
运行结果不会有任何输出。
实例
运行结果:
* $* 和 $@的区别 *
很多关于shell的书本上写当它们被双引号包含时,$* 会将所有参数作为一个整体,而$@ 会将各个参数分开。但是,我在运行脚本的时候并没有发现这样的情况。我是在Ubuntu1204版本中测试的。代码如下
命令替换是指shell可以先执行命令,将输出结果暂时保存,在适当的地方输出
示例:
变量替换
示例:
结果如下:
if … fi 语句
if … else … fi 语句
if … elif … else … fi 语句
if … fi 语句的语法
**注意:**expression 和方括号之间必须有空格。否则会有语法错误
示例:
if … else … fi语句语法
示例:
if … elif …fi语句语法
示例:
算数运算符
bash中实现数学运算的语法。
- 使用expr表达式计算工具。
- [1+2]−[1+2]
- ((1+2))
使用expr时需要注意:
- 表达式和运算符之间要有空格。
- 完整的表达式要被“包含起来。
示例:
关系运算符
关系运算符只支持数字,不支持字符串。除非字符串的值是数字。
示例:
布尔运算符
示例:
字符串运算符
示例:
文件测试运算符
文件测试运算符用于检测文件的各种属性
示例:
运行结果:
双引号与单引号的区别
单引号:单引号中的任何字符都会原样输出,单引号中的变量是无效的。单引号中不能出现单引号。
双引号:双引号中可以有变量,双引号中可以出现转义字符。
示例:
运行结果如下:
字符串的几种用法
bash支持一维数组(不支持多维数组),并且没有限定数组的大小。数组元素的下标由0开始编号,获取数组中的元素要利用下标,下标跨越式整数或者算术表达式,其值应大于或等于0。
数组的定义有3种方式
数组的读取格式
读取数组元素值的一般格式是:
示例:
case工作方式如上所示。取值后面必须为关键字 in ,每一模式必须以右括号结束。取值可以为变量或者常数。匹配发现取值符合某一模式后,其间所有命令开始执行直至 ;;。(;; 类似C语言的break)
取值将检测匹配的每一个模式,一旦模式匹配,则执行完匹配模式相应的内容后不再继续其他模式。如果无一匹配模式,使用 * 捕获该值。在执行相对应内容。
示例:
运行结果:
for循环一般格式为
列表是一组值(数组、字符串等)组成的序列,每个值通过空格分隔。每循环一次,就将列表中的下一个值赋给变量。
运行结果:
Shell中while循环
while循环格式
示例:
Shell中until循环
until循环的格式为:
command 一般为条件表达式,如果返回值为false,则继续执行循环语句,否则跳出循环。
示例:
循环中可以使用break关键字和continue关键字跳出循环,用法如C程序中的break和continue
函数的参数:
调用函数的时可以向其传递参数。在函数体内部。通过n的像是获取参数的值(和获取脚本的参数一样)。当n的值大于等于10时,获取参数需要加大括号,如n的像是获取参数的值(和获取脚本的参数一样)。当n的值大于等于10时,获取参数需要加大括号,如{11}。
函数的调用:
函数的调用只需要给出函数名即可。不需要加括号。
如果希望直接从终端调用函数,可以将函数定义在主目录下的 .profile 文件中。这样每次登陆后,在命令提示符后面输入函数名字就可以直接调用
函数可以使用unset命令删除
示例:
运行结果:
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]
- ((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 is zero"; else echo "string length isn't zero"; fi if [ -n $a -a -n $b ]; then echo "string length isn't zero" else echo "string length is zero"; fi if [ $a -a $b ];then echo "string length isn't zero" else echo "string length is 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
运行结果:
$ ./test.sh test.sh test.sh is not block file test.sh is not str file test.sh is not directory file test.sh is ordinary file test.sh not SGID bit test.sh not Sticky not bit test.sh is not pipe file test.sh not SUID bit test.sh is read file test.sh is write file test.sh is execute file test.sh is not zero test.sh exists [关于SUID,SGID,Sticky的属性请参考:](http://blog.csdn.net/u011641885/article/details/45442053)
Shell中的字符串
Shell中的字符串可以用双引号,也可以用单引号,也可以不用引号。如:#!/bin/bash a="abc" b=edf c='hij' echo $a echo $b echo $c
双引号与单引号的区别
单引号:单引号中的任何字符都会原样输出,单引号中的变量是无效的。单引号中不能出现单引号。
双引号:双引号中可以有变量,双引号中可以出现转义字符。
示例:
#!/bin/bash a="abc" b=edf echo "$a" echo '$b'
运行结果如下:
$ ./test1.sh abc $b
字符串的几种用法
#!/bin/bash a="abc" b=edf echo "$a"$b"" ####**字符串的拼接** 输出结果是abcedf
#!/bin/bash a="abc" echo ${#a} ####**获取字符串的长度**
#!/bin/bash a="abc" echo ${a:1:2} ####**提取字符串** 输入结果是bc
#!/bin/bash a="hello world" echo `expr index "$a" d` ##在字符串$a中查找字符d第一次出现的位子 ####**查找字符或字符串**
Shell中的数组
定义数组bash支持一维数组(不支持多维数组),并且没有限定数组的大小。数组元素的下标由0开始编号,获取数组中的元素要利用下标,下标跨越式整数或者算术表达式,其值应大于或等于0。
数组的定义有3种方式
array_name=("hello" "world") #各元素直接用空格隔开 array_name=( hello world) #各元素直接用换行隔开 c[0]=hello c[2]=world #单独定义数组的各个元素
数组的读取格式
读取数组元素值的一般格式是:
${array_name[index]}
示例:
#!/bin/bash a=("hello" "world") b=( hello world) c[0]=hello c[2]=world echo "${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语句格式如下:case 值 in 模式1) command1 command2 command3 ;; 模式2) command1 command2 command3 ;; *) command1 command2 command3 ;; esac
case工作方式如上所示。取值后面必须为关键字 in ,每一模式必须以右括号结束。取值可以为变量或者常数。匹配发现取值符合某一模式后,其间所有命令开始执行直至 ;;。(;; 类似C语言的break)
取值将检测匹配的每一个模式,一旦模式匹配,则执行完匹配模式相应的内容后不再继续其他模式。如果无一匹配模式,使用 * 捕获该值。在执行相对应内容。
示例:
#!/bin/bash case $1 in -f) echo "FILE" ;; -d) echo "DIR" ;; *) echo "NONE" ;; esac
运行结果:
$ ./test.sh -f FILE $ ./test.sh -d DIR $ ./test.sh NONE $ ./test.sh -g NONE
Shell循环
Shell中for循环for循环一般格式为
for 变量 in 列表 do command1 command2 ..... done
列表是一组值(数组、字符串等)组成的序列,每个值通过空格分隔。每循环一次,就将列表中的下一个值赋给变量。
#!/bin/bash for loop in `date` do echo $loop done
运行结果:
$ ./test.sh 六 5月 2 22:32:38 HKT 2015
Shell中while循环
while循环格式
while command do Statement(s) to be executed if command is true done ##command 一般为测试条件,当条件为真是执行
示例:
#!/bin/bash while read VALUE do echo $VALUE done ##从标准输入中读取字符串
Shell中until循环
until循环的格式为:
until command do Statement(s) to be executed if command is false done
command 一般为条件表达式,如果返回值为false,则继续执行循环语句,否则跳出循环。
示例:
#!/bin/bash a=0 until [ ! $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语句,会将最后一条命令运行结果作为返回值。 ##使用 $? 接收函数返回值
函数的参数:
调用函数的时可以向其传递参数。在函数体内部。通过n的像是获取参数的值(和获取脚本的参数一样)。当n的值大于等于10时,获取参数需要加大括号,如n的像是获取参数的值(和获取脚本的参数一样)。当n的值大于等于10时,获取参数需要加大括号,如{11}。
函数的调用:
函数的调用只需要给出函数名即可。不需要加括号。
如果希望直接从终端调用函数,可以将函数定义在主目录下的 .profile 文件中。这样每次登陆后,在命令提示符后面输入函数名字就可以直接调用
函数可以使用unset命令删除
unset .f function_name #一定要在函数名前加上 .f 参数
示例:
#!/bin/bash fun (){ 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 20 10 20 The sum of two numbers is 30
Shell文件包含
shll可以将外部脚本的内容合并到当前脚本shell中包含脚本格式
. filename
或者
source filename
注意:被包含的脚本不需要执行权限也可以执行。
示例:
#!/bin/bash . ./test1.sh $1 $2 echo test1.sh run over
执行结果:
$ ll test1.sh -rw-rw-r-- 1 gino gino 121 5月 2 23:46 test1.sh $ cat test1.sh #!/bin/bash fun (){ echo $1 echo $2 return $(($1+$2)) } fun $1 $2 ret=$? echo "The sum of two numbers is $ret" $ ./test2.sh 1 2 1 2 The sum of two numbers is 3 test1.sh run
相关文章推荐
- 学习 shell脚本之前的基础知识
- shell 脚本基础知识详细介绍(二)
- Linux学习3_学习shell脚本前应具备的基础知识
- shell脚本基础知识
- Shell脚本基础知识及案例
- SHELL脚本的基础知识2——使用结构化命令
- Linux基础-shell脚本知识整理和脚本编写----------变量、运算符、流程控制、函数、计划任务(发送邮件)
- 学习shell脚本之前的基础知识[图文]
- 学习shell脚本之前的基础知识[图文]
- shell脚本基础知识(下)
- Shell脚本基础知识
- SHELL脚本的基础知识4——处理用户输入
- 第十二章 学习 shell脚本之前的基础知识
- shell脚本基础知识(上)
- Shell脚本基础知识
- 学习shell脚本之前的基础知识
- Shell脚本基础知识
- 学习shell脚本之前的基础知识
- 第13章 学习 shell脚本之前的基础知识