当前位置:网站首页>shell运算详解,看这一篇就够了!

shell运算详解,看这一篇就够了!

2022-08-10 18:10:00 InfoQ

计算机编程就是三大步:输入、运算、输出

那么计算机运算有哪些呢,计算机能做哪些运算呢?

我们来看看常见的计算机运算

一、赋值运算



赋值运算符 =

a=10 
 name='baism'
 
 重点:字符串必须用引号引起来

二、算术运算(四则运算)


2.1 运算符与命令

四则运算符:

+
 → 加

-
 → 减

 *
 → 乘

 \
 → 除

扩展:
 %
 → 取余

 **
 → 开方

运算命令:

  • 整形运算– 
    expr
    – 
    let
     $(())
    – 
    bc
  • 浮点运算– 
    bc

2.2 整形运算

expr 
命令:

只能做整数运算,格式比较古板,注意空格

[[email protected] ~]# expr 1 + 1
2
[[email protected] ~]# expr 5 - 2
3
[[email protected] ~]# expr 5 \* 2 #注意*出现应该转义,否则认为是通配符
10
[[email protected] ~]# expr 5 / 2
2
[[email protected] ~]# expr 5 % 2
1

let
命令:

只能做整数运算,且运算元素必须是变量,无法直接对整数做运算

[[email protected] ~]# let a=100+3;echo $a
103
[email protected] ~]# let a=100-3;echo $a
97
[[email protected] ~]# let a=100/3;echo $a
33
[[email protected] ~]# let a=100*3;echo $a
300
[[email protected] ~]# let a=100%3;echo $a
1
[[email protected] ~]# let a=100**3;echo $a
1000000
[[email protected] ~]# a=100
[[email protected] ~]# let a++;echo $a
101
[[email protected] ~]# let a--;echo $a
100
[[email protected] ~]# let a-=3;echo $a
97
[[email protected] ~]# let a+=5;echo $a
102

双小圆括号运算,在shell中
(( ))
也可以用来做数学运算

[[email protected] ~]# echo $(( 100+3))
103
[[email protected] ~]# echo $(( 100-3)) 
97
[[email protected] ~]# echo $(( 100%3))
1
[[email protected] ~]# echo $(( 100*3))
300
[[email protected] ~]# echo $(( 100/3))
33
[[email protected] ~]# echo $(( 100**3)) #开方运算
1000000

2.3 浮点运算

浮点运算是采用的命令组合的方式来实现的 
echo “scale=N;表达式”|bc

[[email protected] ~]# echo "scale=2;3+100"|bc
103
[[email protected] ~]# echo "scale=2;100-3"|bc
97
[[email protected] ~]# echo "scale=2;100/3"|bc
33.33
[[email protected] ~]# echo "scale=2;100*3"|bc
300

2.4 练习案例

2.4.1 实现一个四则运算计算器
案例思考: 计算器的功能: 
+
 
 
*
 
 \

实现步骤:

  • 要求用户传输三个参数,num1 算术运算符 num2
  • 运算输出结果

实现代码

#!/bin/bash

#Author: li za
#Release: 
#Description: 简单计算器

echo "$1 $2 $3"|bc
2.4.2 内存使用率统计,要求打印内存使用率
案例思考:

  • 内存总量 获得方式是什么 free top /proc/meminfo
  • 内存使用量
  • 内存使用率公式 使用量/总量*100%

实现步骤:

  • 获取内存总量
  • 获取内存使用量
  • 运算输出结果

实现代码

#!/bin/bash

#Author: li za
#Release: 
#Description:内存使用率计算脚本

#free
#1、获得内存总量
memory_total=`free -m|grep -i "mem"|tr -s " "|cut -d " " -f2`

#2、获得内存使用的量
memory_use=`free -m|grep -i "mem"|tr -s " "|cut -d " " -f3`

#3、计算输出
#运算的时候是否需要小数点 浮点运算,要考虑使用的命令 (难点 重点)
#echo "内存使用率: $((memory_use*100/memory_total))%"
#难点:浮点运算中,同优先级的情况下,大数除以小数 尽可能保证精确
echo "内存使用率: `echo "scale=2;$memory_use*100/$memory_total"|bc`%"

三、比较运算



计算机除了
算术
赋值运算
外,还有
比较运算

比如说比较两个数的关系,比较两个字符串的关系【用户登录系统】等

3.1 整形比较运算

 运算符解释:

 精确比较:
 -eq 等于 equal

 -gt 大于

 -lt 小于

 模糊比较:
 -ge 大于或等于

 -le 小于或等于

 -ne 不等于

通过test命令比较两个整数关系

[[email protected] ~]# test 100 -gt 300;echo $?
1
[[email protected] ~]# test 100 -ge 300;echo $?
1
[[email protected] ~]# test 100 -eq 300;echo $?
1
[[email protected] ~]# test 100 -le 300;echo $?
0
[[email protected] ~]# test 100 -lt 300;echo $?
0
[[email protected] ~]# test 100 -ne 300;echo $?
0

备注:linux命令test只能比较两个整数的关系,不会返回结果,需要通过$?才能看到结果

3.2 练习案例

3.2.1 写一个脚本实现对两个证书关系的判断
案例思考:

两个数有几种关系?

  • 大于
  • 小于
  • 等于

实现步骤

  • 交互或者外传参的方式获得两个整数
  • 判断关系
  • 输出结果实现代码

#!/bin/bash

#Author: li za
#
#Release: 
#Description:判断两个数的关系

#1、输入两个数,$1 $2

#2、判断两个数关系
if [ $1 -gt $2 ];then
 #3、输出结果
 echo "$1 > $2 "
elif [ $1 -eq $2 ];then
 echo "$1 = $2"
else
 echo &quot;$1 < $2&quot;
fi
3.2.2 判断两个浮点数的关系
案例思考
shell中的浮点类型如何做比较运算?

默认情况下shell是不能判断浮点的,那么在linux中又避免不了需要进行浮点运算,那怎么解决

解决思路如下:

  • 两个数据同时放大到整数倍
  • 处理掉小数点位,保留整数位
  • 进行整形判断

实现代码

#!/bin/bash

#Author: li za
#
#Release: 
#Description:判断两位小数点的关系

#1、交互或者外传参的方式获得两个整数
#$1 $2
[ $# -lt 2 ]&&echo &quot;need two args&quot;&&exit 1

#采用外传参的方式接收数据并放大100倍,并处理为整数
num1=`echo &quot;scale=2;$1*100&quot;|bc|cut -d &quot;.&quot; -f1`
num2=`echo &quot;scale=2;$2*100&quot;|bc|cut -d &quot;.&quot; -f1`

#2、比较运算
if [ $num1 -gt $num2 ];then
 #3、输出结果
 echo &quot;$1 > $2&quot;
elif [ $num1 -lt $num2 ];then
 echo &quot;$1 < $2&quot;
else
 echo &quot;$1 = $2&quot;
fi

3.3、字符串比较运算

3.3.1 字符串比较运算符
运算符解释,注意字符串一定别忘了使用引号引起来

 == 等于 
 != 不等于
 -n 检查字符串的长度是否大于0 
 -z 检查字符串的长度是否为0
3.3.2 比较两个字符串关系
[[email protected] ~]# test 'root' == 'root';echo $?
0
[[email protected] ~]# test 'root' != 'root1';echo $?
0
[[email protected] ~]# name=
[[email protected] ~]# test -n &quot;$name&quot;;echo $?
1
[[email protected] ~]# test -z &quot;$name&quot;;echo $?
0
3.3.3 练习案例
案例需求:

模拟一个linux文本界面登陆程序,要求账号密码验证成功进入系统,账号密码验证失败退回登陆界面

案例思考:

  • 熟悉linux文本界面登陆步骤
  • 熟悉字符串比较运算

案例步骤:

  • 预设正确账号、密码
  • 输出提示登录信息并实现交互登录
  • 输出密码输入信息并实现交互
  • 判断输入是否正确
  • 1.正确,进入系统
  • 2.不正确 继续运行该脚本

实现代码

#!/bin/bash

#Author: li za
#Created Time: 
#Release: 
#Description: 仿真登陆
####
default_account='root'
default_pw='123456'


######main
#1、清屏
clear
#2、输出提示信息
echo &quot;CentOS Linux 8 (Core)&quot;
echo -e &quot;Kernel `uname -r` on an `uname -m`\n&quot;

#3、交互输入登陆名
echo -n &quot;$HOSTNAME login: &quot;
read account

#4、交互输入密码
read -s -t30 -p &quot;Password: &quot; pw

#5、判断用户输入是否正确
if [ &quot;$default_account&quot; == &quot;$account&quot; ] && [ &quot;$default_pw&quot; == &quot;$pw&quot; ];then
 clear
 echo -e &quot;\nwelcome to root&quot;
else
 echo &quot;用户名或密码错误...&quot;
 #输入错误,再次调用本脚本
 sh $0
fi

四、逻辑运算



完成一个任务中需要多个条件都满足或者多个条件中只要满足一个即可,那么这就是我们的逻辑运算。

通过多个条件判断结果,才能得出结论

4.1 逻辑运算应用场景

多条件同时判断

4.2 逻辑运算符

​ 逻辑与运算 &&

​ 逻辑或运算 ||

​ 逻辑非运算 !

逻辑运算秘籍

逻辑运算注意事项:
 逻辑与、或运算都需要两个或以上条件
 逻辑非运算只能一个条件
 
 口诀: 逻辑与运算 真真为真 真假为假 假假为假
 逻辑或运算 真真为真 真假为真 假假为假
 逻辑非运算 非假为真 非真为假
 
 
逻辑与或的短路运算

逻辑与中靠前的条件中出现了假,后面的就不在判断了,因为已经是假的了

逻辑或中靠前的条件中出现了真,后不在往后判断了,结果已经为真了

4.3 练习案例

明白了逻辑运算符和逻辑运算的口诀和短路运算后,看一个案例

上一个字符串运算练习案例(3.3.3)中练习的是仿真用户登录,判断登陆的方式是
分步判断
的,既
先判断用户名
,不管是否正确都会继续判断密码的正确性,这样是两步判断

既然已知用户名是错误的啦,完全没必要在判断密码的正确性了,因为结果都一样,你不能进入系统

既然判断一个用户输入的用户名和密码是否正确,且一个不正确就不能进入系统,那么我们可以这么去思考一下:两个条件全为真则进入系统,两个条件一个为假则重新登陆

这样是不是就满足了逻辑与运算了,同时思考逻辑与运算的短路运算,逻辑与条件中的判断顺序是从前往后,前边一个条件为假的时候,后边的条件就不用判断了,那么就减少了判断的次数,加快了运算速度
4.3.1 升级版的仿真用户登录系统
案例需求

使用逻辑运算写一个仿真用户登录验证程序

案例思路

  • 输入用户名
  • 输入密码
  • 与运算返回结果

案例代码

#!/bin/bash
echo &quot;CentOS linux 8 (Core)&quot;
echo -e &quot;Kernel `uname -r` on an `uname -m` \n&quot;

#1、输入用户名
echo -n &quot;$HOSTNAME login: &quot;
read myuser

#echo -n &quot;password: &quot;
#read -s -t 5 -n 2 pw

#2、输入密码
read -p &quot;password: &quot; -s -t 5 -n 6 pw

#3、与运算返回结果
[ $myuser == 'root' ] && [ $pw == '123456' ] && echo yes || echo no

五、文件判断(文件类型、权限、新旧判断)



linux的设计思路:一切皆文件,对文件系统的操作其实可以狭隘的理解为对文件的操作

如果希望对文件类型和权限或者两个文件做新旧或者是否同一个文件进行判断

5.1、test判断命令

命令功能
: 检测文件类型和比较运算

命令用法

 test [命令选项] 表达式

命令选项

-d 检查文件是否存在且为目录
-e 检查文件是否存在
-f 检查文件是否存在且为文件
-r 检查文件是否存在且可读
-s 检查文件是否存在且不为空
-w 检查文件是否存在且可写
-x 检查文件是否存在且可执行
-O 检查文件是否存在并且被当前用户拥有
-G 检查文件是否存在并且默认组为当前用户组
-nt file1 -nt file2 检查file1是否比file2新
-ot file1 -ot file2 检查file1是否比file2旧 
-ef file1 -ef file2 检查file1是否与file2是同一个文件,判定依据的是i节点

以上只列出部分命令选项,详细的可以通过:man test获得。

命令用法练习:

文件类型

[[email protected] ~]# test -f /etc/passwd;echo $?
0
[[email protected] ~]# test -f /etc;echo $?
1
[[email protected] ~]# test -d /etc;echo $?
0

权限判断

[[email protected] ~]# test -x /root/anaconda-ks.cfg ;echo $?
1
[[email protected] ~]# ll /root/anaconda-ks.cfg 
-rw-------. 1 root root 1216 6月 26 09:06 /root/anaconda-ks.cfg
[[email protected] ~]# test -r /root/anaconda-ks.cfg ;echo $?
0

[[email protected] ~]# test -w /root/anaconda-ks.cfg ;echo $?
0

5.2 练习案例

案例需求

写一个平滑关闭服务脚本

案例思路

  • 判断服务进程文件是否存在,存在读取PID并判断是否存在进程
  • 进程存在就使用Kill命令结束服务
  • 不存在就报“服务已经结束“

案例步骤

  • 检查服务PID文件
  • 检查进程是否存在
  • 杀死进程

案例代码

#!/bin/bash

#Author: li za
#
#Release: 
#Description:找到服务的PID号,如果服务开启则杀死,否则提示服务已经关闭或不存在

#1、判断PID
#注意PID的路径,如果服务的PID不在这里可以做个软连接
if [ -f /var/run/$1.pid ];then
 #2、如果存在
 PID=`cat /var/run/$1.pid`
 #3、统计进程数
 process_num=`ps aux|grep $PID|wc -l`
 #5、判断进程数大于2则杀死
 if [ $process_num -ge 2 ];then
 kill -s QUIT $PID 
 else
 #5、判断小于2则提示进程不存在,同时删除服务PID文件
 echo &quot;service $1 is close&quot;
 rm -f /var/run/$1.pid
 fi
else
 #2、不存在
 echo &quot;service $1 is close&quot;
fi

原网站

版权声明
本文为[InfoQ]所创,转载请带上原文链接,感谢
https://xie.infoq.cn/article/46855ba0bae554afe40a086f0