对于一台计算机而言,其硬件受系统内核的控制,使用者想要控制计算机,就必须有与系统内核进行通信的手段。而shell就是使用者与计算机进行通信的手段之一。从命名上看,shell实际上是相对于kernel(内核)而言,指系统与外界(使用者)进行接触的部分,一个提供系统功能给用户使用的软件,它接受来自用户的指令,而后调用相应的应用程序。
为了知足不一样的需求,shell提供了两种执行命令方式:linux
ryeshen@~$ cat /etc/shells /bin/sh /bin/bash /sbin/nologin /usr/bin/sh /usr/bin/bash /usr/sbin/nologin /bin/tcsh /bin/csh /bin/ksh /bin/zsh而linux默认是用的解释器是bash。在脚本头能够声明本脚本所使用的解释器,
单引号:不保留特殊符号的功能,括号内内容仅做为纯文本进行使用。
如:正则表达式
ryeshen@~$ echo "I am $name" I am someone ryeshen@~$ echo 'I am $name' I am $name
反引号:引号内内容会被做为命令先被执行,命令的结果做为引号的输出。$()的效果与之相同
如:shell
ryeshen@~$ echo I am `pwd` I am /home/asl ryeshen@~$ echo I am $(pwd) I am /home/asl
ryeshen@~$ echo `echo \$SHELL` /bin/bash ryeshen@~$ echo $(echo \$SHELL) $SHELL ryeshen@~$ echo `echo \\$SHELL` $SHELL ryeshen@~$ echo $(echo \\$SHELL) \/bin/bash ryeshen@~$ echo `echo \` > ryeshen@~$ echo $(echo \\) \参考的文章的解释是“反引号齐自己就对\进行了转义,保留了齐自己意思,若是咱们想在反引号中起到\的特殊意义,咱们必须使用2个\来进行表示”。
#shell脚本中#表示行注释 array=(0 1 2 3 4) array[101]=101 #直接经过 数组名[下标] 就能够对其进行引用赋值。 #若是下标不存在,自动添加新一个数组元素 unset array[101] #使用unset清除指定值 unset array #使用unset清除整个数组
echo ${array[2]} #使用下标获取值 echo ${a[@]} #使用@或*获取数组全部值 echo ${a[*]}
输出结果:数组
2 0 1 2 3 4 0 1 2 3 4
#${数组名[@或*]:起始位置:长度} newArray=(${array[@]:1:3}) #先截取数组"1 2 3",再将截取到的数组赋给newArray
for a in ${arr[@]} do echo "$a" done
a="one,two,three,four" OLD_IFS="$IFS" #使用临时变量保存环境变量IFS的值 IFS="," #给环境变量IFS赋值,这个值用来切割字符串 arr=($a) #字符串切分 IFS="$OLD_IFS" #还原IFS
if …; then … elif …; then … else … fi注意格式中分号;的使用。
ryeshen@~$ if echo "123"; then > echo "123" > fi 123 123
( ): 1. 用于数组的初始化
2. 指令群组(command group),即用括号将一组命令包括起
来,这组命令共用一个shell子进程,所以能够分享自定义变量等。
(( )): 至关于命令let,用于算数运算。举个例子:bash
ryeshen@~$ ((a=1+1)); echo $a 2 ryeshen@~$ ((a=1+1)); echo $a 2
[ ]和[[ ]]的区别:
如上所说,[实际上是一个指令,所以使用判断中字符串时最好用双引号括住,
且>、<必须改写成>和\<(>,<是重定向符)。
另外,在使用&&和||时,必须写成 [ cond1 ] && [ cond2 ] 的形式。
[[ ]]则是bash的关键字。能够直接使用>、<、&&、||,如[[ a>1 && b>2 ]]。
[[ ]]中字符串未双引号括住的话,能进行正则表达式匹配。如:函数
ryeshen@~$ [[ ab == a* ]] && echo "ok" ok
if语句支持的运算符/操做符:(能够理解为是[指令的参数,就像rm -rf同样)学习
for var in …; do do something done for (( cond1; cond2; cond3 )) do do something done
应用示例:ui
#输出1 2 3 4 …… 10 for i in $(seq 10); do #这里是用seq指令生成了"1 2 3 …… 10"的字符串 echo $i; done; #判断输入的字符串是否是文件名 for file in $*; do # $*指从命令行读入的参数,如输入"test.sh a.xml b.txt c.pdf",则$*=(a.xml b.txt c.pdf) if [ -f "$file" ]; then echo "INFO: $file exists" else echo "ERROR: $file not exists" fi done;
while [ cond1 ] && { || } [ cond2 ] …; do do something done
until [ cond1 ] && { || } [ cond2 ] …; do do somethingdone应用示例:
# 逐行输出/etc/hosts文件内容 while read line; do echo $line; done < /etc/hosts; # 这里能读入/etc/hosts,是由于<将文件重定向到read指令
case var in pattern 1 ) … ;; pattern 2 ) … ;; *) … ;; esac
另外提一下shfit,它能够将入参左移,即进行赋值:$1=$2;$2=$3;$3=$4……
case能够与shfit结合使用,用于根据入参进行处理,举例以下:
shell脚本test.sh:spa
#!/bin/bash while [ $# -gt 0 ]; do case $1 in -a) shift; echo a-$1; shift; ;; -b|-d) shift; echo bd-$1; shift; ;; -c) shift; echo c-$1; shift; ;; *) echo unkown; shift; esac done
输出:命令行
ryeshen@~$ ./test.sh -a 1 -c 2 -b 3 -d 3 a-1 c-2 bd-3 bd-3
functionname() { do something } function func() { do something }
func param1 param2 ... # 函数内使用$#,$1等方式获取参数属性和参数,与脚本获取入参相似
func ret=$? #使用$?获取函数的执行结果 ret=`func` #使用反单引号执行函数并将返回值赋值给变量
+ 脚本中定义的变量可在函数中使用
+ 函数中可用local关键字声明属于本身的,不被外部可见的局部变量
学习过shell的基础知识后,最大的感觉是原觉得是 shell脚本的特殊用法事实上是有规律可推理的。在此以前,虽然知道[]两边要加空格、使用while read $line;do……done < a.txt能够逐行读入文件等零碎的知识点,但只是知其然殊不知其因此然。了解了shell的特殊符号的含义后,才发现这些东西并不是只能靠死记硬背,而是有规则可循的。