基本语法:

格式一

expr +、 -、 \*、/、 %(加、减、乘、除、求余)

格式二

"$((运算式))"或者"$[运算式]"

基本运算符

Shell 和其他编程语言一样,支持多种运算符,包括:

  • 算术运算符
  • 关系运算符
  • 布尔运算符
  • 字符串运算符
  • 文件测试运算符
  • 赋值运算符
  • 逻辑运算符
(1)算术运算符
运算符 说明 示例
+ 单目正号 ((+3))结果为3
- 单目负号 ((-3))结果为-3
++ 自增(变量前,先运算后取值;变量后,先取值后运算) b=2((a=++b))后a为3,b为3;((a=b++))后a为2,b为3
自减(变量前,先运算后取值;变量后,先取值后运算) b=2((a=--b))后a为1,b为1;((a=b--))后a为2,b为1
+ expr 3 + 2结果为5
- expr 3 - 2结果为1
* expr 3 \* 2结果为6
/ expr 3 / 2结果为1
% 取模 expr 3 % 2结果为1
** 幂运算 ((3**2))结果为9

注意:

  • expr可用于整数运算,也可以处理字符串,使用expr进行运算时,表达式和运算符之间必须加空格,乘号*和小括号()前要加\转义(小括号是左右括号前都要加\转义)。

  • (( expression ))会对算术表达式求值,如果表达式的值不是0,则返回状态是0,否则返回状态是1,这和let "expression"等价。

  • (( ))前面加上$符号可以获取(( ))命令的执行结果,即整个表达式的值。

    (( ))只能进行整数运算,不能对浮点数或字符串进行运算。

(2)关系运算符

test[][[ ]]中使用的关系运算符:

运算符 说明 示例
-eq (equal)检测两个数是否相等,是返回0,否则返回1。 如果a为3,b为2,则[ ${a} -eq ${b} ]返回1
-ne (not equal)检测两个数是否不相等,是返回0,否则返回1。 如果a为3,b为2,则[ ${a} -ne ${b} ]返回0
-gt (greater than)检测左边的数是否大于右边的,是返回0,否则返回1。 如果a为3,b为2,则[ ${a} -gt ${b} ]返回0
-lt (less than)检测左边的数是否小于右边的,是返回0,否则返回1。 如果a为3,b为2,则[ ${a} -lt ${b} ]返回1
-ge (greater equal)检测左边的数是否大于等于右边的,是返回0,否则返回1。 如果a为3,b为2,则[ ${a} -ge ${b} ]返回0
-le (less equal)检测左边的数是否小于等于右边的,是返回0,否则返回1。 如果a为3,b为2,则[ ${a} -le ${b} ]返回1

(())中使用的关系运算符:

运算符 说明 示例
== 检测两个数是否相等,是返回0,否则返回1。 如果a为3,b为2,则((a==b))返回1
!= 检测两个数是否不相等,是返回0,否则返回1。 如果a为3,b为2,则((a!=b))返回0
> 检测左边的数是否大于右边的,是返回0,否则返回1。 如果a为3,b为2,则((a>b))返回0
>= 检测左边的数是否大于等于右边的,是返回0,否则返回1。 如果a为3,b为2,则((a>=b))返回0
< 检测左边的数是否小于右边的,是返回0,否则返回1。 如果a为3,b为2,则((a<b))返回1
<= 检测左边的数是否小于等于右边的,是返回0,否则返回1。 如果a为3,b为2,则((a<=b))返回1

注意:

  • 关系运算符只支持整数数字,不支持字符串,除非字符串的值是整数数字。
  • (( ))中表达式的值不是0,返回状态才是0,否则返回状态是1,(( ))进行整数比较的时候表达式的值与(())返回状态正好相反,表达式的值为0,返回状态为1,表达式的值为1,返回状态为0。
(3)布尔运算符
运算符 说明 示例
-a 与运算,两个表达式都为true才返回true。 如果a为3,b为2,则[ ${a} -gt 1 -a ${b} -lt 1 ]返回false
-o 或运算,有一个表达式为true,则返回true。 如果a为3,b为2,则[ ${a} -gt 1 -o ${b} -lt 1 ]返回true
! 非运算,表达式为true,则返回false,否则返回true。 如果b为2,则[ ! ${b} -lt 1 ]返回true

-a-o)必须在[]中或配合test命令使用。

(4)字符串运算符

可以在test[][[ ]]中使用:

运算符 说明 示例
==、= 如果两个字符串相等,则为true。 如果a为"expression",b为"expansion",则[[ ${a} == ${b} ]]返回1
!= 如果两个字符串不相等,则为true。 如果a为"expression",b为"expansion",则[[ ${a} != ${b} ]]返回0
> 如果左边字符串在字典顺序上排在右边字符串之后,则为true。 如果a为"expression",b为"expansion",则[[ ${a} > ${b} ]]返回0
< 如果左边字符串在字典顺序上排在右边字符串之前,则为true。 如果a为"expression",b为"expansion",则[[ ${a} < ${b} ]]返回1
-z string 如果字符串的长度为零,则为true。 如果a为"expression",则[[ -z ${a} ]]返回1
-n string 如果字符串的长度不为零,则为true。 如果a为"expression",则[[ -n ${a} ]]返回0
$ 检测字符串是否不为空,不为空返回 true。 如果a为"expression",则[[ ${a} ]]返回0,与-n用法类似

注意:

  • test[][[ ]]中使用字符串运算符===!=><只能比较字符串(只是字符串的值为数字时可以把它当成数字来比较,这只是字符串比较的结果与数值比较正好巧合,不推荐用它来比较数字,如[[ -3 < -2 ]]返回1,[[ 03 < 2 ]]返回0,[[ 1.5 == 1.50 ]]返回1,都是错误结果。
  • 如果要使用test[][[ ]]比较整数,需使用关系运算符-eq-ne-gt-lt-ge-le,推荐在(( ))中使用关系运算符==!=><>=<=进行整数比较。
  • test[]使用><需要加\转义,[[ ]]则不需要转义。
  • 使用test[][[ ]]则没有>=<=,可以通过[ ${a} \> ${b} -o ${a} == ${b} ][[ ${a} > ${b} || ${a} == ${b} ]]这种方式替代。
  • test[]会进行单词拆分,而[[ ]]不会进行单词拆分。
  • 当与[[ ]]一起使用时,<>使用当前区域设置按字典顺序排序,test命令使用ASCII排序。
(5)文件测试运算符
运算符 说明 示例
-a file 如果文件存在,则为true。 [ -a ${file} ]
-b file 如果文件存在并且是个块设备文件,则为true。 [ -b ${file} ]
-c file 如果文件存在并且是个字符设备文件,则为true。 [ -c ${file} ]
-d file 如果文件存在并且是个目录,则为true。 [ -d ${file} ]
-e file 如果文件存在,则为true。 [ -e ${file} ]
-f file 如果文件存在并且是个普通文件(既不是目录也不是设备文件),则为true。 [ -f ${file} ]
-g file 如果文件存在并且设置了set-group-id位,则为true。 [ -g ${file} ]
-h file、-L file 如果文件存在并且是个符号链接,则为true。 [ -h ${file} ]
-k file 如果文件存在并且设置了“sticky”位,则为true。 [ -k ${file} ]
-p file 如果文件存在并且是个命名管道(FIFO),则为true。 [ -p ${file} ]
-r file 如果文件存在并且可读,则为true。 [ -r ${file} ]
-s file 如果文件存在并且大小大于0,则为true。 [ -s ${file} ]
-u file 如果文件存在并且设置了set-user-id位,则为true。 [ -u ${file} ]
-w file 如果文件存在并且可写,则为true。 [ -w ${file} ]
-x file 如果文件存在并且可执行,则为true。 [ -x ${file} ]
-G file 如果文件存在并且被有效组id所拥有,则为true。 [ -G ${file} ]
-N file 如果文件存在并且自上次读取后被修改,则为true。 [ -N ${file} ]
-O file 如果文件存在并且被有效用户id所拥有,则为true。 [ -O ${file} ]
-S file 如果文件存在并且是个套接字,则为true。 [ -S ${file} ]
file1 -ef file2 如果file1和file2指向相同的设备和inode号,则为true。 [ ${file1} -ef ${file2} ]
file1 -nt file2 如果file1比file2更新(根据修改日期),或者file1存在而file2不存在,则为true。 [ ${file1} -nt ${file2} ]
file1 -ot file2 如果file1比file2更旧,或者file2存在而file1不存在,则为true [ ${file1} -ot ${file2} ]
(6)赋值运算符
运算符 说明 示例
= 赋值 c=3 a=${c}则a为3
+= 加赋值 如果a为3,b为2,则((a+=b))后a为5,b为2
-= 减赋值 如果a为3,b为2,则((a-=b))后a为1,b为2
*= 乘赋值 如果a为3,b为2,则((a*=b))后a为6,b为2
/= 除赋值 如果a为3,b为2,则((a/=b))后a为1,b为2
%= 取模赋值 如果a为3,b为2,则((a%=b))后a为1,b为2
<<= 左移位赋值 如果a为3,b为2,则((a<<=b))后a为12,b为2
>>= 右移位赋值 如果a为3,b为2,则((a>>=b))后a为0,b为2
&= 按位与赋值 如果a为3,b为2,则((a&=b))后a为2,b为2
|= 按位或赋值 如果a为3,b为2,则((a|=b))后a为3,b为2
^= 按位异或赋值 如果a为3,b为2,则((a^=b))后a为1,b为2

可以使用(( ))let命令进行运算,let(( ))用法类似,都是用于整数运算。

(7)逻辑运算符
运算符 说明 示例
&& 逻辑与 如果a为3,b为2,则[[ ${a} > 1 && ${b} < 1 ]]返回false
|| 逻辑或 如果a为3,b为2,则[[ ${a} > 1 || ${b} < 1 ]]返回true
! 逻辑非 如果b为2,则[[ ! ${b} < 1 ]]返回true

&&||可以在[[ ]](( ))中使用,不能在test[]中使用,!可以在[[ ]]中使用,不能在(( ))中使用。

(8)位运算符
运算符 说明 示例
<< 左移位 ((3<<2))结果为12
>> 右移位 ((6>>2))结果为1
& 按位与 ((6&3))结果为2
| 按位或 ((6|3))结果为7
^ 按位异或 ((6^3))结果为5
~ 按位非 ((~6))结果为-7

注:加粗部分为较为常用的运算符

概念理解、区分

(1)[[[ 的区别

区别一:

在 [ 中使用逻辑运算符,需要使用 -a(and)或者 -o(or)。

在 [[ 中使用逻辑运算符,需要使用 && 或者 ||。

区别二:

[] 是 bash 内部命令,与test是等同的,所以字符串比较符 > 和 < 需要转义,否则就变成 io 重定向了。

[[ 是 bash 关键字,不会做命令扩展,所以 < 和 > 不需要进行转义。但是语法相对严格,如在 [ 中可以用引号括起操作符,[[ 则不行。如:if [ "-z" "ab" ]。

[root@abc-1 ~]# [[ 6>A ]] && echo Y ||echo N
-bash: unexpected token 284 in conditional command
-bash: syntax error near `6>'
[root@abc-1 ~]# [[ 6 > A ]] && echo Y ||echo N
N
[root@abc-1 ~]# [ 6 > A ] && echo Y ||echo N
Y

解释,数字的ASCCII应该小于大写字母,使用[[]]的结果是正确的。

区别三:

[[ 可以做算术扩展,[ 则不行。

区别四:

在[ ]中==是字符匹配,在[[ ]]中是模式匹配

区别五:

[ ]不支持正则匹配,[[ ]]支持用=~进行正则匹配

[root@abc-1 ~]# var="hello"
[root@abc-1 ~]# [ $var =~ "ll" ] && echo Y || echo N
-bash: [: =~: binary operator expected
N
[root@abc-1 ~]# [[ $var =~ "ll" ]] && echo Y || echo N
Y

解释,[[ ]]判断变量var的值是否包含字符串ll,[]报错,[[]]输出正确

区别六:

[ ]中如果变量没有定义,那么需用双引号引起来,[[ ]]中不需要

总结:

[[]] []
< 排序比较 不支持(仅部分Shell解释器支持<)
> 排序比较 不支持(仅部分Shell解释器支持>)
&& 逻辑与 -a 逻辑与
|| 逻辑或 -o 逻辑或
== 模式匹配 ==字符匹配
=~正则匹配 不支持
()分组测试 不支持(仅部分Shell解释器支持())

实践

(1)暂无


参考:

https/blog.csdn.net/RtxTitanV/article/details/115007727

https://www.runoob.com/linux/linux-shell-basic-operators.html

Linux扩展篇-shell编程(三)-shell运算符的更多相关文章

  1. Linux入门篇(六)——Shell(二)

    这一系列的Linux入门都是本人在<鸟哥的Linux私房菜>的基础上总结的基本内容,主要是记录下自己的学习过程,也方便大家简要的了解 Linux Distribution是Ubuntu而不 ...

  2. 【Shell编程】Shell程序设计

    1.Shell简介   作为Linux灵感来源的Unix系统最初是没有图形化界面的,所有的任务都是通过命令行来实现的.因此,Unix的命令行系统得到了很大的发展,逐步成为一个功能强大的系统.   Sh ...

  3. Linux入门篇(五)——Shell(一)

    这一系列的Linux入门都是本人在<鸟哥的Linux私房菜>的基础上总结的基本内容,主要是记录下自己的学习过程,也方便大家简要的了解 Linux Distribution是Ubuntu而不 ...

  4. Linux shell编程02 shell程序的执行 及文件权限

    第一个shell脚本 1.       shell编程的方式 交互式shell编程 非交互式shell编程:执行的语句存放到一个文件 shell脚本:可以任意文件名,建议扩展名为sh 2.       ...

  5. 书写优雅的shell脚本(三) - shell中exec解析

    参考:<linux命令.编辑器与shell编程> <unix环境高级编程> exec和source都属于bash内部命令(builtins commands),在bash下输入 ...

  6. shell编程01—shell基础

    01.学习shell编程需要的知识储备 1.vi.vim编辑器的命令,vimrc设置 2.命令基础,100多个命令 3.基础.高端的网络服务,nfs,rsync,inotify,lanmp,sersy ...

  7. Linux Shell编程三

    case分支条件语句. case "string" in pattern_1) commands ;; pattern_2) commands ;; *) commands ;; ...

  8. linux shell编程(三) if 和 for

    if 条件判断: 单分支的if语句if 判断条件: then statement1fi双分支的if语句if 判断条件;then statement1 statementelse statement3f ...

  9. shell编程(三)之条件判断(if语句)

    练习:写一个脚本判断当前系统上是否有用户的默认shell为bash: 如果有,就显示有多少个这类用户:否则,就显示没有这类用户: #!/bin/bash # grep '\<bash$' /et ...

  10. Linux shell编程 4 ---- shell中的循环

    1 for循环 1 for语句的结构 for variable in values; do statement done 2 for循环通常是用来处理一组值,这组值可以是任意的字符串的集合 3 for ...

随机推荐

  1. Borůvka MST算法

    当我认为最MST(最小生成树)已经没有什么学的了,才发现世界上还有个这个kruskal和prim结合的玩意 Borůvka 运用并查集的思想,先将每一个初始点集初始化为有且只有自己的点集,然后每一次合 ...

  2. 牛客网-SQL专项训练10

    ①SQL语句中与Having子句同时使用的语句是:group by 解析: SQL语法中,having需要与group by联用,起到过滤group by后数据的作用. ②下列说法错误的是?C 解析: ...

  3. 面试官:在原生input上面使用v-model和组件上面使用有什么区别?

    前言 还是上一篇面试官:来说说vue3是怎么处理内置的v-for.v-model等指令? 文章的那个粉丝,面试官接着问了他另外一个v-model的问题. 面试官:vue3的v-model都用过吧,来讲 ...

  4. BizWorks助力企业应用的高效开发与复用

    简介: BizWorks作为企业级云原生应用数字工作台,能很好地支撑企业数字中台建设.云原生应用开发.企业资产运营管理等场景.本文不会全面介绍BizWorks平台的能力,而是着重介绍BizWorks在 ...

  5. C#类型后加问号?

    C# 可空类型(Nullable)说明_w3cschool 细说Nullable<T>类型 - Sweet-Tang - 博客园 (cnblogs.com) 值类型变量不能null,加问号 ...

  6. dotnet 启动进程传入不存在的文件夹作为工作目录行为变更

    本文记录在 dotnet 下,启动进程,传入不存在的文件夹作为进程的工作目录,分别在 .NET Framework 和 .NET Core 的行为 在 dotnet 6 下,可以使用 ProcessS ...

  7. 使用WebSocket实现实时多人答题对战游戏

    前言 前两章教程,我们使用WebSocket的基础特性打造了一个小小聊天室,并在第二章对其进行了集群化改造. 系列教程回顾: [WebSocket]第一章:手把手搭建WebSocket多人在线聊天室( ...

  8. WebStorm2023安装prettier并生效

    1.首先去File > Settings > Plugins 里下载并install插件 Prettier 2.在settings里搜索prettier,按图片所示设置一下Apply 3. ...

  9. 7、yum 仓库服务与 PXE 网络装机

    1.部署 yum 软件仓库 1.1.使用本地 yum 挂载 umount /dev/sr0 mount /dev/sr0 /media/mkdir /root/yum.bakmv /etc/yum.r ...

  10. 书生浦语大模型全链路开源体系-书生浦语大模型实战营学习笔记1&大语言模型2

    大语言模型-2.书生浦语大模型全链路开源体系 书生浦语大模型实战营学习笔记-1.认识书生浦语大模型全链路开源体系 本系列随笔学习搬运第二期书生浦语大模型实战营的相关内容,通过使用InternLM的一套 ...