shell 编程
一、简介
- sh在运行时实际上是创造一个子进程在执行命令,而主进程负责等到最后回收子进程。
- echo $? --->上一个命令成功执行返回0,失败返回1
- echo 是返回文本或变量值
- source 与 空格.空格 等价,也能执行sh脚本,属于内建命令,他与sh区别就是,它直接在当前shell下执行sh代码,而sh启动脚本会生成一个新的进程来跑。
二、基本语法
- env打印环境变量
- set打印本地变量
- 环境变量:当前目录存储在环境变量里面
- 本地变量:在栈上跑
- 本地变量变成环境变量 用 export
- 删除环境变量unset
在sh里取变量前面要加上$符号:echo $变量名
- 通配符:*匹配任意字符;?匹配任意一个;[]匹配若干字符
- ``或$() 把一句话转换成一个命令执行
单引号、双引号都扩字符串。但双引号扩的是一个变量会展开。
{ }使用
- 第一种模式:${var:num},这种模式时,shell在var中提取第num个字符到末尾的所有字符。若num为正数,从左边0处开始;若num为负数,从右边开始提取字串,但必须使用在冒号后面加空格或一个数字或整个num加上括号,如${var: -2}、${var:1-3}或${var:(-2)}。
- 第二种模式:${var:num1:num2},num1是位置,num2是长度。表示从$var字符串的第$num1个位置开始提取长度为$num2的子串。不能为负数。
- 第三种模式:${var/pattern/pattern}表示将var字符串的第一个匹配的pattern替换为另一个pattern。
第四种模式:${var//pattern/pattern}表示将var字符串中的所有能匹配的pattern替换为另一个pattern。
总结一下{}()常用。
变量1=(${变量2//字符/空格})
- 将变量2按照字符进行分割成一个元组,赋给变量1
三、shell脚本语法
- test=[ ]测试一个条件是否成立,成立返回0,假返回1;用test+echo $?判断
- [ -d+文件名 ] 判断是否为一个目录
- [ -f+文件名 ] 判断是否为一个文件
分支语句
if [ 条件 ]
then 条件为真执行该语句
else 条件为假执行该语句
fi
(if 冒号:在sh里表示恒久为真)
if [ 条件1 ]
then 条件一满足执行的语句
elif[ 条件2 ]
then 条件2为真执行该语句
else 条件12均为假执行该语句
fi
case/esac
case命令可类比C语言的switch/case语句,esac表示case语句块的结束。
case "$1" in
start)
...变量$1等于start执语句行
;; 相当于break
stop)
...变量$1等于stop执语句行
;;
reload | force-reload)
...变量$1等于reload执语句行
;;
restart)
...
*)
log_success_msg "Usage: nfs-kernel-server {start|stop|status|reload|force-reload|restart}"
exit 1
;;
esac
循环语句
for/do/done
Shell脚本的for循环结构和C语言很不一样,它类似于某些编程语言的foreach循环。例如:
#! /bin/sh
for FRUIT in apple banana pear; do
echo "I like $FRUIT"
done
FRUIT是一个循环变量,第一次循环$FRUIT的取值是apple,第二次取值是banana,第三次取值是pear。再比如,要将当前目录下的chap0、chap1、chap2等文件名改为chap0~、chap1~、chap2~等(按惯例,末尾有~字符的文件名表示临时文件),这个命令可以这样写:
$ for FILENAME in chap?; do mv $FILENAME $FILENAME~; done
while/do/done
while的用法和C语言类似。比如一个验证密码的脚本:
#! /bin/sh
echo "Enter password:"
read TRY
while [ "$TRY" != "secret" ]; do
echo "Sorry, try again"
read TRY
done
函数
和C语言类似,Shell中也有函数的概念,但是函数定义中没有返回值也没有参数列表。例如:
#! /bin/sh
foo(){ echo "Function foo is called";}
echo "-=start=-"
foo
echo "-=end=-"
注意函数体的左花括号'{'和后面的命令之间必须有空格或换行,如果将最后一条命令和右花括号'}'写在同一行,命令末尾必须有;号。
在定义foo()函数时并不执行函数体中的命令,就像定义变量一样,只是给foo这个名字一个定义,到后面调用foo函数的时候(注意Shell中的函数调用不写括号)才执行函数体中的命令。Shell脚本中的函数必须先定义后调用,一般把函数定义都写在脚本的前面,把函数调用和其它命令写在脚本的最后(类似C语言中的main函数,这才是整个脚本实际开始执行命令的地方)。
Shell函数没有参数列表并不表示不能传参数,事实上,函数就像是迷你脚本,调用函数时可以传任意个参数,在函数内同样是用$0、$1、$2等变量来提取参数,函数中的位置参数相当于函数的局部变量,改变这些变量并不会影响函数外面的$0、$1、$2等变量。函数中可以用return命令返回,如果return后面跟一个数字则表示函数的Exit Status。