shell脚本-上篇
shell脚本
变量相关:
引用变量:
a=qwe
echo $a #普通方式
echo $a123 不能加上字符串显示
echo ${a} #可正确界定变量名
echo ${a}123 显示变量并跟上123
内置变量:
$0 执行的sh自身文件名
$1,$2 位置变量
$? 特殊变量。状态码
$* 所有手动传参,参数列表
$@ 所有手动传参,参数列表
$# 所有手动传参,参数总数
$ARNDOM 生成随机数
环境变量:
export name=value
declare 选项
-a 声明数组变量
-i 声明为整数
-x 设为环境变量
-/+ 改变属性,“-”设置,“+”取消
-f 显示所有已经定义的函数
本地变量:
set 变量 #设置本地变量
set [选项] 显示所有变量
-e 整个脚本命令执行错误一个就退出
-u 引用未申明的变量就报错,等同set -o nounset
-o 选项
pipefail 命令有管道时,整个命令的状态码都为0才成功
-x 当执行命令时,打印命令及其参数,类似 bash -x
常用组合:
set -euo pipefail #所有错误,都直接退出,建议在写脚本时,写在开头出,避免脚本出错后继续执行
只读变量:
readonly name 定义只读(静态变量),随shell终止消失
declare -r name
位置变量:
$1,$2... 对应第一个、第二个调用的参数
shift [num] 踢出前面一个参数,如$3位置的参数变成$2的,给的num指定踢出几个参数
局部变量:
local 变量 函数体内的变量
销毁变量:
unset 变量
显示所有环境变量:
export、env、printenv
运算相关:
运算符:
+
-
*
/
% 取模,即取余数,示例:9%4=1,5%3=2
** 乘方
+= i+=10 相当于 i=i+10
-= i-=j 相当于 i=i-j
*=
/=
%=
++ i++,++i
--
运算格式:
let var=i++
var+=1
var=$[i+j]
var=$((i+j))
var=$(expr $i \* $j)
echo 1+2 |bc #使用linux计算器
逻辑运算:
! 非
[ a -a b ] 与
[ a -o b ]] 或
[[ a && b ]]
[[ a || b ]]
条件测试:
语句:
test EXPRESSION
[ EXPRESSION ] test等价
[[ EXPRESSION ]] 支持一元、三元
if [ ] ;then
操作
else
操作
fi
if [ ] ;then
操作
elif [ ] ;then
操作
[else] #可有可无else
fi
条件判断:
数字:
-gt/ge >/>=
-lt/le </<=
-eq/ne =/!=
字符串:
!、--、++、*、~
==、!=、>、<
=~ 左侧字符串是否能够被右侧条件匹配,可用正则、通配符,当需要后面用到正则引用时,数组变量:BASH_REMATCH记录正则分组
-z "string" 检测字符串长度是否为0,为0返回 true
-n "string" 检测字符串长度是否不为 0,不为 0 返回 true
配合通配符:
file=123.log
[[ $file == *.log ]]
配合正则表达式:
#正则不可以用"、'符号包起来,因为把引号当作字符串了
[[ "$FILE" =~ \.log$ ]]
a="12 qwe: "
[[ $a =~ ^([0-9]+ [a-z]+:[[:space:]]) ]] && echo 1
b='abc-123'
[[ $b =~ (.*)-([0-9]+)$ ]] && echo ${BASH_REMATCH} -- ${BASH_REMATCH[0]} ${BASH_REMATCH[1]} ${BASH_REMATCH[2]}
注意:
"*"时为字符
qw*时为通配符
使用通配符、正在表达方式时用:[[ ]]
变量:
-v 变量 变量是否为空
-R 变量 变量是否存在,且被引用
例: 判断变量是否引用
a=123
declare -n b=$a
[ -R b ] &&echo $b
文件存在性测试:
-a file 文件是否存在,存在为真
-e file $?,判断文件、目录是否存在,存在为真
例:
[ -e /dev/sr0 ] && echo ok ||echo error
文件类型存在性:
-b file 判断快设备文件
-c 字符设备
-d 目录文件
-f 普通文件
-S 套接字文件
-L/-h 链接文件
-p 管道文件
文件特殊权限判断:
-r 可读,w,x同
-u 是否存在suid
-g 是否存在sgid
-k sticky权限
文件其他属性判断:
-s 文件为空
-t fd 表示文件描述符是否已打开且与某终端相关
-N 文件自上一次被读取之后是否被修改过
-O 当前用户是否为文件属主
-G 当前用户为文件属组
file1 -ef file2 文件inode是否相同
file1 -nt file2 file1新于file2
file1 -ot file2 file1旧于file2
函数编写: 与C++语法类似
语法1:
function name {
语句
}
语法2:
name() {
return #0-255
}
函数递归
例: 求斐波那契数列
fuct() {
if [ $1 -eq 0 -o $1 -eq 1 ]; then
echo 1
else
echo $[$1*$(fuct $[$1-1])]
fi
}
fuct 5
例: fork炸弹
:(){ :|:& };:
说明:声明:函数,调用:,|开启子shell,再调用:后台并运行。执行:函数