Shell编程笔记
created by cjk on 2019.4.14
一、Shell概述
- Shell的定义:Shell是一个命令解释器,它接收应用程序/用户的命令,调用操作系统内核执行任务。
二、Shell解析器
-
在Linux系统中,有多个Shell解析器,列表配置于/etc/shell文件中
-
常用的解析器有两种:sh和bash,在centos中,sh是一个软连接指向bash,但是在一些系统中,sh也不是指向bash而是指向dash,如Debian和Ubuntu系统
-
默认的Shell解析器:echo $SHELL
三、Shell脚本HelloWorld
-
脚本的格式:以#!/bin/bash开头,用于指定使用哪个解析器解析脚本
-
执行脚本时如果是使用命令调用,如sh test.sh或bash test.sh是不需要执行权限的,如果是直接使用./test.sh的方式运行脚本的话,需要用户对该文件有执行权限
四、Shell脚本多命令处理
- 在实际使用过程中,Shell脚本通常是多个指令集组成的复杂功能。
五、Shell系统变量和自定义变量
-
常用的系统变量
$HOME # 当前系统家目录 $PWD #当前脚本所在路径 $SHELL # 当前使用的shell解释器名称 $USER # 当前执行脚本的用户名称 $MAIL # 邮件保存路径 $RANDOM #生成一个随机数字 $PATH # 执行命令时搜索解释器的路径,相当于windows中的path环境变量
-
如果需要查看所有已定义的系统变量,可以使用env命令查看
-
自定义变量
-
基本语法
- 定义变量
A=12
- 撤销变量
unset A
- 定义静态变量(只读变量),此变量不能被unset
readonly B=3
- 将局部变量提升为全局变量,供其他shell程序使用
A=66 export A
-
-
特殊变量
-
$n:n代表数字,$0代表此脚本路径及名称,$1-$9代表第一到第九个参数,从第十开始需要用大括号包裹参数,如:${10},脚本的参数输入跟在执行命令后即可,以空格隔开
- 基本语法
#!/bin/bash echo "script_name: $0" echo "first_param: $1" echo "second_param: $2"
-
$#:获取所有输入参数的个数,常用于循环中
- 基本语法
#!/bin/bash echo $#
-
$*与$@:$*和$@在直接使用的情况下输出的内容一致,但是在"$*"与"$@"下,前者会把所有参数当成一个整体,后者会把每个参数都区分开来
-
$?:最后一次执行的命令的返回状态,如果这个变量的值为0,证明上一个命令正确执行,如果为非0,则证明上一条命令执行不正确
- 基本语法
#!/bin/bash echo "success command" echo "command execute status: $?" # 正确的返回值0 pws # 错误的不存在的命令 echo "command execute status: $?" # 错误的返回值127
-
六、Shell运算符
- 整数运算:常用的整数运算符有$(())和$[]以及expr
#!/bin/bash
let S=(2+3)*5 # let运算符必须指定一个接收变量,然后才能用于输出
echo $S
echo $[(2+3)*5] # $[]运算符可以很方便计算出四则表达式
echo $(((2+3)*5)) # $(())用法与$[]的一致,只是符号不同
echo $(expr $(expr 2 + 3) * 5) # expr命令不支持括号优先运算,需要使用$()让需要的内容优先运算,且其乘号的表达式为*不能使用*,因为*默认为通配符
- 浮点数运算:浮点运算可以通过bc命令来执行,需要注意的是,bc命令必须搭配echo命令取出运算值
#!/bin/bash
echo "$(echo "3.14*2" | bc)*10.0" | bc # 这个表达式可以解析为先执行echo "3.14*2" | bc命令,得到结果6.28,然后执行echo 6.28*10 | bc命令得到最终运算结果62.8
七、Shell条件判断
-
基本语法:[ condition ],注意[]前后都是有空格的,且条件非空即为true,如[ abc ]返回为true而[]返回为false
-
常用判断条件
- 字符串之间的比较,使用 != 和 = 来进行判断,注意,条件判断符两边都是有空格的
#!/bin/bash test="haha" [ "haha" = $test ] echo $? [ "haha" != $test ] echo $?
-
整数之间的比较
- -lt:小于(less than)
- -le:小于等于(less equal)
- -eq:等于(equal)
- -gt:大于(greater than)
- -ge:大于等于(greater equal)
- -ne:不等于(Not equal)
#!/bin/bash [ 22 -lt 23 ] #如果22是小于33的,那么判断会执行成功,$?返回为0,否则返回非零数 [ $? -ne 0 ] && echo "22 ge 23" || echo "22 lt 23" [ 22 -le 22 ] [ $? -ne 0 ] && echo "22 gt 22" || echo "22 le 22" [ 33 -eq 22 ] [ $? -ne 0 ] && echo "33 ne 22" || echo "33 eq 22" [ 33 -gt 32 ] [ $? -ne 0 ] && echo "33 le 32" || echo "33 gt 32" [ 33 -ge 33 ] [ $? -ne 0 ] && echo "33 lt 33" || echo "33 ge 33" [ 22 -ne 33 ] [ $? -ne 0 ] && echo "22 eq 23" || echo "22 ne 33"
- 浮点数类型的比较
[ $(echo "2.16>3.33" | bc) -eq 0 ] && echo "fail" || echo "success" # 利用bc指令返回是否为0来判断浮点数的大小,返回0说明表达式成立,返回1说明表达式不成立
-
文件权限判断
- -r:有读的权限
- -w:有写的权限
- -x:有执行的权限
- 值得注意的是,该判断方式不能区分是用户权限还是组权限,只要文件有该权限即返回True
- 在root用户下执行判断除非是解除了文件的执行权限,解除文件读和写的权限似乎并没有用,判断依旧会返回True,实际上root用户即使解除了文件的所有权限,依旧是可以进行读和写的,这与文件权限的判断结果一致
#!/bin/bash [ -x ./first.sh ] && echo "first file has execute permission" || echo "no execute permission" [ -w ./first.sh ] && echo "first file has write permission" || echo "no write permission" [ -r ./first.sh ] && echo "first file has read permission" || echo "no read permission"
-
文件类型判断
- -f:文件是否存在且为一个常规的文件file
- -e:文件存在,可以是文件也可以是目录existence
- -d:文件存在,且是一个目录directory
#!/bin/bash [ -f ./first.sh ] && echo "first.sh file exist" || echo "no such file named first.sh" [ -e ./first.sh ] && echo "first.sh file/dir exist" || echo "no file/dir named first.sh" [ -d ./first.sh ] && echo "first.sh dir exist" || echo "no such dir named first.sh"
-
Shell条件判断的小技巧
- 在只有一层if else的情况,判断条件简单的情况下,可以使用判断表达式来代替if else
[ -d ./first.sh ] && echo "first.sh dir exist" || echo "no such dir named first.sh" # 判断当前目录下是否存在first.sh的目录,如果存在,判断表达式[ -d ./first.sh ]将会输出True,因此会执行下一步的 && 操作运算符后面的内容,输出"first.sh dir exist",如果不存在,输出为false,由于与条件被短路就不会执行 && 后的内容了,而会去进一步执行 || 后的内容,利用这种方式就可以简单的达到条件判断的目的了。
八、其他注意点
- 等号赋值时不要习惯性地在两端加上空格,会报错
- Shell脚本中自定义变量的命名最好都以大写命名
- 在bash中,变量默认类型都是字符串类型,无法直接进行数值运算
- 变量的值如果有空格,需要使用双引号或者单引号包裹