1、脚本调试-脚本运行前要进行脚本调试
bash -n /path/to/some_script 检测脚本中的语法错误
bash -x /path/to/some_script 调试执行
2、shell是弱类型编程语言
1)、无须指定变量类型,默认为字符型;变量参与运算会自动进行隐式类型转换;变量无须事先定义可直接调用
如:bash 不支持浮点数
2)变量命名法则
不能使程序中的保留字:例如if, for
只能使用数字、字母及下划线,且不能以数字开头
见名知义
统一命名规则,例如驼峰命名法
3、本地变量
生效范围为当前shell进程,对当前shell 之外的其它shell 进程,包括当前shell 的子shell 进程均无效;
1)、变量赋值:name=‘value’
可以使用引用value:
(1) 可以是直接字串; name=“root"
(2) 变量引用:name="$USER"
(3) 命令引用:name=` COMMAND `, name =$(COMMAND)
"" :弱引用,其中的变量引用会被替换为变量值
'' :强引用,其中的变量引用不会被替换为变量值,而保持原字符串
2)、变量引用即是引用或者使用变量的值,格式为:${name}, $name;前一种格式较为稳妥
3)、显示已定义的所有变量:set
删除变量:unset name
4、环境变量:生效范围为当前shell及其子子孙孙shell进程
变量声明、赋值:
export name=VALUE
declare -x name=VALUE
变量引用:$name, ${name}
显示所有环境变量:
export
env
printenv
删除:unset name
bash 有许多内建的环境变量:PATH, SHELL, USRE,UID,HISTSIZE,HOME,PWD,OLDPWD,HISTFILE,PS1
5、只读变量:只能声名,但不能修改和删除
readonly name=value
declare -r name=value
6、位置变量:在脚本代码中调用通过命令行传递给脚本的参数
$1, $2, … :对应第1 、第2 等参数(但是地址变量$10指的是第一个参数$1和0的组合,例如$1参数是x,那么$10就是x0)
$0: 命令本身,例如/root/bin/arg.sh
$*: 传递给脚本的所有参数,全部参数合为一个字符串
$@: 传递给脚本的所有参数,每个参数为独立字符串
$#: 传递给脚本的参数的个数
$@ $* 只在被双引号包起来的时候才会有差异
例如f1.sh脚本#!/bin/bash
f2.sh “$*”
f2.sh “$@”
7、算术运算
bash 中的算术运算:
+, -, *, /, % (取余), ** (乘方)
实现算术运算:
(1) let var= 算术表达式
(2) var=$[ 算术表达式]
(3) var=$(( 算术表达式))
(4) echo ‘算术表达式’ | bc
乘法符号有些场景中需要转义,如*
bash 有内建的随机数生成器:$RANDOM (1-32767)
echo $[$RANDOM%50] 生成0-49 之间随机数
8、赋值
增强型赋值:+=, -=, *=, /=, %=
let varOPERvalue
例如:let count+=3,意思是变量count自加3 后自赋值
let var++
let var—
后置加加和前置加加
i++ 表示i的值作为表达式的值,然后i自加1
++i 表示i先自加1再作为表达式的值
9、逻辑运算
true, false
1, 0
与:
1 与 1 = 1
1 与 0 = 0
0 与 1 = 0
0 与 0 = 0
或:
1 或 1 = 1
1 或 0 = 1
0 或 1 = 1
0 或 0 = 0
命令true,#true命令执行后#echo $?的返回值是0
命令false,#false命令执行后#echo $?的返回值是非零任意数
短路与&&:exp1 如果为假,exp2就不运算;也是exp1为真,exp2就运算
短路或||:exp1 如果为真,exp2就不运算;也是exp1为假,exp2就运算
异或^:exp1与exp2相同为假,不同为真
10、聚集命令
有两种聚集命令的方法:
• 复合式:date; who | wc –l 命令会一个接一个地运行
• 子shell式 :(date; who | wc -l ) >> /tmp/trace 所有的输出都被发送给单个STDOUT 和STDERR
11、退出状态
进程可以使用退出状态来报告成功或失败
$? 变量保存最近的命令退出状态,可以在脚本中使用,保存的是前一个紧挨着的命令的执行状态
#echo $? 返回值为0代表成功,1-255 代表失败
例如:
#ping -c1 -W1 hostIP &> /dev/null
# echo $?
(第一条命令中:-c1选项表示ping一次,-W1表示1秒)
12、退出状态码
exit [n]:自定义退出状态码
例如,在脚本中最后一行写入exit 99,则脚本运行结束后,无论脚本倒数第二行的命令成功或者失败,则查看退出状态时#echo $?的返回值都是99
注意:脚本中一旦遇到exit 命令,脚本会立即终止,终止退出状态取决于exit 命令后面的数字,若exit命令后无数字,则终止退出状态码取决于此exit命令前一条命令的执行结果成败取0或者非零的任意数
注意:如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码
13、条件测试
测试命令:
• test EXPRESSION
• [ EXPRESSION ]
• [[ EXPRESSION ]],双中括号有更强适用性
注意:若使用第二、三条测试命令,则EXPRESSION 前后必须有空白字符
&&与||是条件性的执行操作符
示例(双引号):
$ test "$A" == "$B" && echo "Strings are equal"
$ test “$A” -eq “$B” && echo "Integers are equal"
简写格式的例子:
$ [ "$A" == "$B" ] && echo "Strings are equal"
$ [ "$A" -eq "$B" ] && echo "Integers are equal"
14、bash 的测试类型
1)、数值测试:
-gt: 是否大于;
-ge: 是否大于等于;
-eq: 是否等于;
-ne: 是否不等于;
-lt: 是否小于;
-le: 是否小于等于;
2)、字符串测试:
== :是否等于;
>: ascii码是否大于ascii码
<: 是否小于
!=: 是否不等于
=~: 左侧字符串是否能够被右侧的PATTERN所匹配
(注意: 此上表达式一般用于[[ ]]中)
-z "STRING" :字符串是否为空,空为真,不空为假
-n "STRING" :字符串是否为空,不空为真,空为假
(注意:用于字符串比较时的用到的操作数都应该使用引号)
3)、文件测试
存在性测试
-a FILE :同-e
-e FILE : 文件存在性测试,存在为真,否则为假;
存在性及类别测试
-b FILE :是否存在且为块设备文件
-c FILE :是否存在且为字符设备文件
-d FILE :是否存在且为目录文件
-f FILE :是否存在且为普通文件
-h FILE 或 -L FILE :是否存在且为符号链接文件
-p FILE :是否存在且为命名管道文件
-S FILE :是否存在且为套接字文件
文件权限测试:-r、-w、-x
文件特殊权限测试:
-g FILE :是否存在且拥有sgid 权限
-u FILE :是否存在且拥有suid 权限
-k FILE :是否存在且拥有sticky权限
文件大小测试:
-s FILE: 是否存在且非空,也即非空为真,#[ -s FILE ]执行后#echo $?的返回值是0
文件是否打开:
-N FILE :文件自上一次被读取之后是否被修改过,也即是atime在mtime前就是自上一次读取后被修改过,#[ -N FILE ]执行后#echo $?的返回值是0
-O FILE :当前有效用户是否为文件属主
-G FILE :当前有效用户是否为文件属组
双目测试:
FILE1 -ef FILE2: FILE1与FILE2是否指向同一个设备上的相同inode,也即是FILE1与FILE2是否是硬链接的关系,如是为真,不是为假
FILE1 -nt/-ot FILE2: FILE1是否新/旧于FILE2,比较的是FILE1与FILE2的修改时间,也即mtime
15、组合测试条件
第一种方式:
COMMAND1 && COMMAND2 并且
COMMAND1 || COMMAND2 或者
! COMMAND 非
如:[ -e FILE ] && [ -r FILE ]
第二种方式:
EXPRESSION1 -a EXPRESSION2 并且
EXPRESSION1 -o EXPRESSION2 或者
! EXPRESSION 非
如:# [ -z “$HOSTNAME” -o "$HOSTNAME" =="localhost.localdomain" ] && hostname www.magedu.com
主机名为空或者是localhost.localdomain,那么就定义主机名为www.magedu.com
# [ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab
如果/bin/cat是存在且为普通文件并且/bin/cat有执行权限,那么就执行cat /etc/fstab
16、使用read 命令来接受输入
read 从标准输入即键盘输入中读取值,分配给一个或多个shell变量
-p 指定要显示的提示信息
用法:read -p “Enter a filename:” FILE
示例:指定文件做为参数,编写脚本判断文件是否为.sh后缀,如果是,添加x权限;不是,则提示xxf
#!/bin/bash
read -p "please input the file:" a
A1=`echo $a | grep -o "\.[^.]\+$"`
[[ "$A1" == ".sh" ]] && chmod +x $a || echo xxf
17、脚本example.sh未赋予权限时,使用bash、source及 .
1)、使用bash运行相当于开了一个子shell example.sh,example.sh里面的变量当前终端shell不可引用;
2)、使用source和 .运行example.sh脚本,就相当于直接在当前终端运行脚本example.sh内变量和命令代码,所有example.sh里面的变量可以为当前终端shell引用
所以可知,bash是给脚本用的,source和 .是给配置文件使用的
例如example.sh脚本位于当前root用户的家目录下,为#!/bin/bash
a=haha
PATH=/XXX
echo PATH=$PATH
cd /tmp
那么如果使用source或者 .来运行脚本example.sh,比如# . /root/example.sh后
输出的结果是PATH=/XXX,同时当前的目录变为/tmp,实际上变量a和PATH是定义于当前终端上了,故而
再#echo $a 的输出结果是haha,而不是为空
#echo $PATH 的输出结果是/XXX,而不再是默认的PATH路径,因为原先的PATH变量被替换
#pwd 的返回值是/tmp,而不是当前root用户的家目录/root
原创文章,作者:18612763863,如若转载,请注明出处:http://www.178linux.com/35548