Linux扩展篇-shell编程(三)-shell运算符
基本语法:
格式一
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运算符的更多相关文章
- Linux入门篇(六)——Shell(二)
这一系列的Linux入门都是本人在<鸟哥的Linux私房菜>的基础上总结的基本内容,主要是记录下自己的学习过程,也方便大家简要的了解 Linux Distribution是Ubuntu而不 ...
- 【Shell编程】Shell程序设计
1.Shell简介 作为Linux灵感来源的Unix系统最初是没有图形化界面的,所有的任务都是通过命令行来实现的.因此,Unix的命令行系统得到了很大的发展,逐步成为一个功能强大的系统. Sh ...
- Linux入门篇(五)——Shell(一)
这一系列的Linux入门都是本人在<鸟哥的Linux私房菜>的基础上总结的基本内容,主要是记录下自己的学习过程,也方便大家简要的了解 Linux Distribution是Ubuntu而不 ...
- Linux shell编程02 shell程序的执行 及文件权限
第一个shell脚本 1. shell编程的方式 交互式shell编程 非交互式shell编程:执行的语句存放到一个文件 shell脚本:可以任意文件名,建议扩展名为sh 2. ...
- 书写优雅的shell脚本(三) - shell中exec解析
参考:<linux命令.编辑器与shell编程> <unix环境高级编程> exec和source都属于bash内部命令(builtins commands),在bash下输入 ...
- shell编程01—shell基础
01.学习shell编程需要的知识储备 1.vi.vim编辑器的命令,vimrc设置 2.命令基础,100多个命令 3.基础.高端的网络服务,nfs,rsync,inotify,lanmp,sersy ...
- Linux Shell编程三
case分支条件语句. case "string" in pattern_1) commands ;; pattern_2) commands ;; *) commands ;; ...
- linux shell编程(三) if 和 for
if 条件判断: 单分支的if语句if 判断条件: then statement1fi双分支的if语句if 判断条件;then statement1 statementelse statement3f ...
- shell编程(三)之条件判断(if语句)
练习:写一个脚本判断当前系统上是否有用户的默认shell为bash: 如果有,就显示有多少个这类用户:否则,就显示没有这类用户: #!/bin/bash # grep '\<bash$' /et ...
- Linux shell编程 4 ---- shell中的循环
1 for循环 1 for语句的结构 for variable in values; do statement done 2 for循环通常是用来处理一组值,这组值可以是任意的字符串的集合 3 for ...
随机推荐
- 【Oracle】力扣简单的练习题
Oracle力扣简单的练习题 请你编写一个 SQL 查询来交换所有的 'f' 和 'm' /* Write your PL/SQL query statement below */ /******** ...
- 第四課-Channel Study File Reader & File Writer
示例描述:从数据库中读取数据并过滤转换为HL7并存放到指定目录;然后读取目录中的HL7文件转换为txt文本并存放到指定目录. 首先在F:\MirthConnect\Test目录下创建Out目录存放输出 ...
- 牛客网-SQL专项训练25
①批处理是指包含一条或多条T-SQL语句的语句组,下列选项中,关于批处理的规则描述正确的是(B) 解析: A选项:不能定义一个check约束后,立即在同一个批处理中使用: C选项:Create def ...
- ZooKeeper 在阿里巴巴的服务形态演进
简介: 本文将给大家介绍下 ZooKeeper 的最佳实践场景,归为了 3 类,分别是:微服务领域,代表的集成产品是 Dubbo/SpringCloud:大数据领域,代表的集成产品是 Flink/Hb ...
- 基于 Flutter 的 Web 渲染引擎「北海」正式开源!
简介: 阿里巴巴历时 3 年自研开发的 Web 渲染引擎北海(英文名:Kraken)正式开源,致力打造易扩展,跨平台,高性能的渲染引擎,并已在优酷.大麦.天猫等业务场景中使用. 作者 | 染陌来源 | ...
- IT人的年夜饭,也太香了吧
简介: 平时的IT人,奋战在修复bug前线,起早与贪黑齐飞,调休共假期待定.到了新春佳节,对于IT人来说,没有什么是比一顿年夜饭更让人熨贴肺腑的了.为了让废寝忘食编程序.闻机起早保运维的IT人过一个 ...
- [FAQ] Sortable 拖拽组件, 火狐浏览器中打开新窗口问题
Q:用了 sortable 组件,在火狐浏览器中进行拖拽时,会打开新窗口 ? Sortable组件地址,https://github.com/SortableJS/Sortable 当前处理方式 ...
- [K8s] Kubernetes 集群部署管理方式对比, kops, kubeadm, kubespray
kops 是官方出的 Kubernetes Operations,生产级 K8s 的安装.升级和管理. 可以看做是适用于集群的 kubectl,kops 可帮助您从命令行创建,销毁,升级和维护生产级, ...
- 全网最详细SpringCloud-实用篇
SpringCloud-实用篇 学习安排 技术分类 1.微服务 ①架构对比 架构 单体架构 分布式架构 描述 将业务的所有功能集中在一个项目中开发,打成一个包部署. 根据业务功能对系统做拆分,每个业务 ...
- pde复习笔记 第一章 波动方程 第三节 分离变量法
教材 谷超豪<数学物理方程>第四版,虽然我们老师用的第三版,但是除了页码对不上,习题多了一点,也似乎没有多少区别. 打算开个新栏专门总结一下pde的各种计算问题,在图书馆算的手麻了,但是习 ...