zl程序教程

您现在的位置是:首页 >  后端

当前栏目

运维--shell脚本知识【常用内建变量、判断表达式】

变量运维shell -- 常用 脚本 判断 知识
2023-09-11 14:16:24 时间

在编写程序的运维脚本时,经常用到shell的各种内建变量、判断表达式,本文针对此进行相关整理。

本文会包含如下内容:

  • shell的常见内建变量
  • ${ }的一些特异功能
  • 条件判断的并或(and or)
  • shell的常用判断表达式

本篇文章适合人群:技术专家、开发人员、运维人员

1.常见内建变量

  • $0 这个脚本的执行名字

  • $n 这个脚本的第n个参数值,n=1..9

  • $* 这个脚本的所有参数,此选项参数可超过9个。

  • $@  跟$*类似,但是可以当作数组用。但是当被双引号“”包含时,“$*”会将所有的参数作为一个整体,以“$1 $2 …$n”的形式输出所有参数;“$@”会将各个参数分开,以“$1” “$2”…”$n”的形式输出所有参数

  • $# 这个脚本的参数个数

  • $$ 这个脚本的PID(脚本运行的当前进程ID号)

  • $! 执行上一个指令的PID(运行在后台的最后一个作业的PID(进程ID))

  • $? 执行上一个指令的返回值 (显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误)

  • $- 显示shell使用的当前选项,与set命令功能相同

2. ${ }的一些特异功能

  • $(command) 等价于 `command` , 如 echo $(pwd)
  • ${var} 是变量替换,如echo ${name}_aa
  • ${ }的一些特异功能,如定义一个变量: file=/dir1/dir2/dir3/my.file.txt 可以用${ }分别替换获得不同的值:

${file#*/} 拿掉第一个 / 及其左边的字符串:dir1/dir2/dir3/my.file.txt

${file##*/} 拿掉最后一个 / 及其左边的字符串:my.file.txt

${file#*.} 拿掉第一个 . 及其左边的字符串:file.txt

${file##*.} 拿掉最后一个 . 及其左边的字符串:txt

${file%/*} 拿掉最后一个 / 及其右边的字符串:/dir1/dir2/dir3

${file%%/*} 拿掉第一个 / 及其右边的字符串:(空值)

${file%.*} 拿掉最后一个 . 及其右边的字符串:/dir1/dir2/dir3/my.file

${file%%.*} 拿掉第一个 . 及其右边的字符串:/dir1/dir2/dir3/my

  • 对变量值进行字符串截取

${file:0:5} 提取最左边的 5 个字节:/dir1

${file:5:5} 提取第 5 个字节右边的连续 5 个字节:/dir2

  • 对变量值里的字符串作替换:

${file/dir/path} 将第一个 dir 替换为 path:/path1/dir2/dir3/my.file.txt

${file//dir/path} 将全部 dir 替换为 path:/path1/path2/path3/my.file.txt

  • ${#var} 可计算出变量的长度,如${#aparams[@]} 计算数组的长度

  • ${!var}是引用间接变量;如下:显示hello

v1="v2"
v2="hello"
echo ${!v1}
  • $[]与\$(())用途一致:用来作整数运算。在 bash 中,$(( ))的整数运算符号大致有这些: \+ - * / % & | ^ ! AND、OR、XOR、NOT运算 注意:这种扩展计算是整数型的计算,不支持浮点型和字符串等。

若是逻辑判断,表达式为真则为1,假则为0, 如echo $((1>2)),输出0

  • 三目运算以及重定义变量值,如a=1; b=2;echo $[3>2?a:b],  输出1

2.1 区别()和{}

相同点:

  • ()和{}都是把一串的命令放在括号里面,如果命令在一行,则命令之间用;隔开

不同点:

  • ()只是把一串命令重新开一个子shell进行执行,不影响当前shell环境;{}对一串命令在当前shell执行,影响当前shell环境
  • ()最后一个命令不用分号,{}最后一个命令要用分号
  • ()里的第一个命令和左边括号不必有空格,{}的第一个命令和左括号之间必要要有一个空格

3. 条件判断中的并或

3.1 并且

条件 c1并且条件c2

if [ c1 -a c2 ]; then
…
fi

#或者

if [ c1 ] && [ c2 ]; then
…
fi

3.2 或者

条件 c1或者 条件c2

if [ c1 -o c2 ]; then
…
fi

#或者

if [ c1 ] || [  c2 ]; then
…
fi

4. 常用判断表达式

4.1 文件/目录判断

  • [ -a FILE ] 如果 FILE 存在则为真。

  • [ -b FILE ] 如果 FILE 存在且是一个块文件则返回为真。

  • [ -c FILE ] 如果 FILE 存在且是一个字符文件则返回为真。

  • [ -d FILE ] 如果 FILE 存在且是一个目录则返回为真。

  • [ -e FILE ] 如果 指定的文件或目录存在时返回为真。

  • [ -f FILE ] 如果 FILE 存在且是一个普通文件则返回为真。

  • [ -g FILE ] 如果 FILE 存在且设置了SGID则返回为真。

  • [ -h FILE ] 如果 FILE 存在且是一个符号符号链接文件则返回为真。

  • [ -k FILE ] 如果 FILE 存在且已经设置了冒险位则返回为真。

  • [ -p FILE ] 如果 FILE 存并且是命令管道时返回为真。

  • [ -r FILE ] 如果 FILE 存在且是可读的则返回为真。

  • [ -s FILE ] 如果 FILE 存在且大小非0时为真则返回为真。

  • [ -u FILE ] 如果 FILE 存在且设置了SUID位时返回为真。

  • [ -w FILE ] 如果 FILE 存在且是可写的则返回为真。(一个目录为了它的内容被访问必然是可执行的)

  • [ -x FILE ] 如果 FILE 存在且是可执行的则返回为真。

  • [ -O FILE ] 如果 FILE 存在且属有效用户ID则返回为真。

  • [ -G FILE ] 如果 FILE 存在且默认组为当前组则返回为真。(只检查系统默认组)

  • [ -L FILE ] 如果 FILE 存在且是一个符号连接则返回为真。

  • [ -S FILE ] 如果 FILE 存在且是一个套接字则返回为真。

  • [ FILE1 -nt FILE2 ] 如果 FILE1 比 FILE2 新, 或者 FILE1 存在但是 FILE2 不存在则返回为真。

  • [ FILE1 -ot FILE2 ] 如果 FILE1 比 FILE2 老, 或者 FILE2 存在但是 FILE1 不存在则返回为真。

  • [ FILE1 -ef FILE2 ] 如果 FILE1 和 FILE2 指向相同的设备和节点号则返回为真。

4.2 逻辑判断

  • [ ! EXPR ] 逻辑非,如果 EXPR 是false则返回为真。

  • [ EXPR1 -a EXPR2 ] 逻辑与,如果 EXPR1 and EXPR2 全真则返回为真。

  • [ EXPR1 -o EXPR2 ] 逻辑或,如果 EXPR1 或者 EXPR2 为真则返回为真。

  • [ ] || [ ] 用OR来合并两个条件

  • [ ] && [ ] 用AND来合并两个条件

4.3 数值判断

  • [ INT1 -eq INT2 ] INT1和INT2两数相等返回为真 ,=

  • [ INT1 -ne INT2 ] INT1和INT2两数不等返回为真 ,<>

  • [ INT1 -gt INT2 ] INT1大于INT2返回为真 ,>

  • [ INT1 -ge INT2 ] INT1大于等于INT2返回为真,>=

  • [ INT1 -lt INT2 ] INT1小于INT2返回为真 ,<

  • [ INT1 -le INT2 ] INT1小于等于INT2返回为真,<=

4.4 字符串判断

  • [ -z STRING ] 如果STRING的长度为零则返回为真,即空是真

  • [ -n STRING ] 如果STRING的长度非零则返回为真,即非空是真

  • [ STRING1 ]  如果字符串不为空则返回为真,与-n类似

  • [ STRING1 == STRING2 ] 如果两个字符串相同则返回为真

  • [ STRING1 != STRING2 ] 如果字符串不相同则返回为真

  • [ STRING1 < STRING2 ] 如果 “STRING1”字典排序在“STRING2”前面则返回为真。

  • [ STRING1 > STRING2 ] 如果 “STRING1”字典排序在“STRING2”后面则返回为真。