当前位置: 首页 > news >正文

9.Shell脚本修炼手册---数值计算实践

Shell 数值计算实践

文章目录

    • Shell 数值计算实践
      • 算术运算符
      • $(()) 双小括号数值运算命令
        • $(()) 双小括号数值运算的基础语法
        • $(()) 双小括号运算实践
      • let 命令
      • expr 命令
        • expr 命令的基本用法
        • expr 的企业级实战案例
      • bc 命令
      • awk 命令实现计算
      • $[] 符号的运算

算术运算符

在 Shell 中进行数值计算时,我们需要用到各种算术运算符。这些运算符和我们平时接触的数学运算符号很相似,只是在 Shell 中有特定的使用规则。下面为大家详细介绍常见的 Shell 算术运算符:

  • +、-(一元):表示正数或负数,比如 +5 表示正 5,-3 表示负 3。
  • +、-(二元):表示加法和减法,比如 2+3 结果为 5,5-2 结果为 3。
  • *、/、%:分别表示乘法、除法、取余(取模)。例如 2*3=66/2=37%3=1(7 除以 3 的余数是 1)。
  • **:表示幂运算,比如 2**3 表示 2 的 3 次方,结果为 8。
  • ++、–:自增和自减运算符,既可以放在变量前面(如 ++a),也可以放在变量后面(如 a++)。前置时先运算再使用变量值,后置时先使用变量值再运算。
  • !、&&、||:逻辑运算符,分别表示逻辑非(取反)、逻辑与(and)、逻辑或(or)。比如 !true 结果为假,true && false 结果为假,true || false 结果为真。
  • <、<=、>、>=:比较运算符,分别表示小于、小于等于、大于、大于等于。比如 3<5 结果为真,5>=6 结果为假。
  • ==、!=、=:比较运算符,=== 表示相等(字符串比较时也可用 =),!= 表示不相等。比如 3==3 结果为真,4!=5 结果为真。
  • <<、>>:移位运算符,<< 表示向左移位,>> 表示向右移位(二进制层面的操作)。比如 8<<1(8 的二进制是 1000,左移 1 位变为 10000,即 16)。
  • ~、|、&、^:按位运算符,~ 是按位取反,| 是按位或,& 是按位与,^ 是按位异或(针对二进制位的运算)。
  • =、+=、-=、*=、/=、%=:赋值运算符,a=5 表示给 a 赋值 5;a+=1 等价于 a=a+1,即 a 的值加 1 后重新赋值给 a;其他运算符类似。

在 Shell 中,常用的算术运算命令有以下几种,它们各自有不同的特点和适用场景:

  • $(()):专门用于整数运算,效率高,用法灵活,是运维人员常用的运算方式。
  • let:功能和 $(()) 类似,也用于整数运算。
  • expr:可用于整数运算,还能处理字符串长度、匹配等操作。
  • bc:Linux 自带的计算器程序,支持整数和小数运算。
  • $[]:用于整数运算,语法简单。
  • awk:既能处理整数运算,也能处理小数运算,精度较高。
  • declare:通过 -i 参数定义整数变量,之后可直接对变量进行运算。

$(()) 双小括号数值运算命令

双小括号 $(()) 是 Shell 中进行数值运算和数值比较的高效工具,用法灵活,在实际工作中经常被使用。

$(()) 双小括号数值运算的基础语法

$(()) 的使用方式主要有以下几种:

  • ((变量 = 表达式)):先计算表达式,再将结果赋值给变量。例如 ((i=i+1)) 表示将 i+1 的结果重新赋值给 i。 ⚠️ 注意:不能直接用 echo ((i=i+1)) 输出结果,需要用 echo $((i=i+1)) 才能输出运算后的值。
  • ** 变量 =(((表达式))**:在 \)(())前加\(,表示将表达式的运算结果赋值给变量。例如 i=\)((i+1))和上面的((i=i+1)) 效果相同。
  • ((比较表达式)):可进行比较操作,还能结合逻辑与(&&)、逻辑或(||)用于条件判断。例如 ((8>7 && 5==5)) 表示判断 8 大于 7 且 5 等于 5,结果为真。
  • echo $((表达式)):直接输出表达式的运算结果。例如 echo $((2+1))\ 会输出 3。
$(()) 双小括号运算实践

实验流程:通过多个示例演示 $(()) 的基本用法,包括简单计算、复杂计算、特殊运算符使用、比较判断、自增自减操作及变量赋值,观察运算结果并理解其逻辑。

示例 1:简单的数值计算

# 直接计算1+1的结果并输出,$((...))会先计算内部表达式,再通过echo输出
[bq@shell ~]$ echo $((1+1))
2# 计算6*3的结果并输出
[bq@shell ~]$ echo $((6*3))
18# 用((...))定义变量i并赋值为5
[bq@shell ~]$ ((i=5))# 计算i*2的结果并重新赋值给i(此时i=5*2=10)
[bq@shell ~]$ ((i=i*2))# 输出变量i的值,验证运算结果
[bq@shell ~]$ echo $i
10

示例 2:复杂的数值计算

# 计算表达式1+2^3-4%3的结果并赋值给a(2^3=8,4%3=1,所以1+8-1=8)
[bq@shell ~]$ ((a=1+2**3-4%3))# 输出a的值,验证结果
[bq@shell ~]$ echo $a
8# 将表达式的结果同时赋值给b和a(先计算表达式,再赋值给a,最后将a的值赋给b)
[bq@shell ~]$ b=$((a=1+2**3-4%3))# 输出b的值,结果和a一致
[bq@shell ~]$ echo $b
8# 直接输出表达式的运算结果
[bq@shell ~]$ echo $((a=1+2**3-4%3))
8# 计算1到100的和(公式:n*(n+1)/2),赋值给a
[bq@shell ~]$ a=$((100*(100+1)/2))# 输出a的值(100*101/2=5050)
[bq@shell ~]$ echo $a
5050# 直接输出1到100的和
[bq@shell ~]$ echo $((100*(100+1)/2))
5050

示例 3:特殊运算符号的使用

# 定义a=8,然后计算a+=1(即a=a+1)的结果并输出(8+1=9)
[bq@shell ~]$ a=8;echo $((a+=1))
9# 计算a的平方(a此时为9,9^2=81)并输出
[bq@shell ~]$ echo $((a**2))
81

示例 4:比较和判断

# 判断3<8是否成立(成立),执行后无输出,通过$?查看返回值(0表示真)
[bq@shell ~]$ ((3<8))
[bq@shell ~]$ echo $?  # $?是上一条命令的返回值,0为成功(真),非0为失败(假)
0# 直接输出3<8的判断结果(1表示真,0表示假)
[bq@shell ~]$ echo $((3<8))
1# 判断3>8是否成立(不成立),通过$?查看返回值(1表示假)
[bq@shell ~]$ ((3>8))
[bq@shell ~]$ echo $?
1# 直接输出3>8的判断结果(0表示假)
[bq@shell ~]$ echo $((3>8))
0# 输出3==3的判断结果(1表示真)
[bq@shell ~]$ echo $((3==3))
1# 用if判断8>7且5==5是否成立(成立则输出yes)
[bq@shell ~]$ if ((8>7 && 5==5));then echo yes;fi
yes

示例 5:自增(++)和自减(–)运算符的使用

# 定义a=10
[bq@shell ~]$ a=10# 输出a++的结果(a++是后置自增,先输出a的原值10,再将a加1)
[bq@shell ~]$ echo $((a++))
10# 此时a的值已变为11,输出验证
[bq@shell ~]$ echo $a
11# 输出--a的结果(--a是前置自减,先将a减1(11-1=10),再输出结果)
[bq@shell ~]$ echo $((--a))
10# 此时a的值为10,输出验证
[bq@shell ~]$ echo $a
10

总结

  • 后置自增 / 自减(a++a--):先输出变量当前值,再对变量进行加 1 / 减 1 操作。
  • 前置自增 / 自减(++a--a):先对变量进行加 1 / 减 1 操作,再输出变量的新值。

示例 6:通过 $(()) 运算后赋值给变量

# 定义num=99
[bq@shell ~]$ num=99# 计算num+1的结果(99+1=100)并输出(此时num的值未改变)
[bq@shell ~]$ echo $((num+1))
100# 将num+1的结果赋值给num(此时num=100)
[bq@shell ~]$ num=$((num+1))# 输出num的值,验证结果
[bq@shell ~]$ echo $num
100

let 命令

let 命令用于执行整数运算,语法格式为 let 表达式,其功能和 ((表达式)) 完全相同。

实验流程:通过对比普通赋值和 let 命令赋值的差异,理解 let 命令的作用。

示例

# 定义i=2
[bq@shell ~]$ i=2# 直接用i=i+8赋值(Shell会当作字符串处理,不会计算)
[bq@shell ~]$ i=i+8# 输出i的值,结果为字符串"i+8",而非计算后的10
[bq@shell ~]$ echo $i
i+8# 重新定义i=2
[bq@shell ~]$ i=2# 用let命令执行i=i+8(会进行数值计算,等价于((i=i+8)))
[bq@shell ~]$ let i=i+8# 输出i的值,结果为10(2+8=10)
[bq@shell ~]$ echo $i
10

expr 命令

expr(全称 evaluate expressions,即 “求值表达式”)命令不仅可以进行整数运算,还能处理字符串长度计算、字符串匹配等操作。

expr 命令的基本用法

实验流程:通过简单的加减乘运算,观察 expr 命令的语法要求(如空格、特殊符号转义)。

示例

# 计算2+2,但运算符前后没有空格,expr会当作字符串输出
[bq@shell ~]$ expr 2+2  # 等价于直接输出"2+2"
2+2# 计算2+2,运算符前后有空格,expr会进行数值计算并输出结果4
[bq@shell ~]$ expr 2 + 2  # 等价于echo $((2+2))
4# 直接用*计算2*2,会报错(*在Shell中是通配符,被误解)
[bq@shell ~]$ expr 2 * 2
expr: syntax error# 用\转义*,表示乘法,计算2*2的结果并输出4
[bq@shell ~]$ expr 2 \* 2 
4

使用 expr 的注意事项

  • 运算符和参与计算的数字前后必须有至少一个空格,否则 expr 会当作字符串处理,不会进行运算。
  • 乘法运算符 * 必须用反斜线 \ 转义,因为 Shell 中 * 是通配符(匹配任意字符),不转义会被 Shell 误解。
expr 的企业级实战案例

实验流程:通过 4 个实战案例(判断整数、验证文件扩展名、计算字符串长度、筛选短单词),掌握 expr 在实际场景中的应用。

示例 1:判断一个变量值是否为整数

实现原理:expr 进行数值计算时,要求参与运算的必须是整数。如果将变量和一个已知整数(非 0)相加,若命令返回值为 0(成功),则变量为整数;若返回值非 0(失败),则变量不是整数。

# 定义变量i为整数5
[bq@shell ~]$ i=5# 用expr计算i+5(5+5=10),输出结果10
[bq@shell ~]$ expr $i + 5
10# 查看上一条命令的返回值(0表示成功,说明i是整数)
[bq@shell ~]$ echo $?
0# 定义变量i为非整数a
[bq@shell ~]$ i=a# 用expr计算i+5,因i不是整数,报错
[bq@shell ~]$ expr $i + 5
expr: non-integer argument# 查看返回值(2表示失败,说明i不是整数)
[bq@shell ~]$ echo $?
2

此外,还可以用 expr match 结合正则表达式判断是否为整数(^[0-9]+$ 匹配 1 个或多个数字):

# 变量i为非整数a,用match匹配整数格式,返回0(不匹配)
[bq@shell ~]$ i=a
[bq@shell ~]$ expr match "$i" "^[1-9][0-9]*$"  # ^[1-9][0-9]*$:匹配非0开头的整数(排除0)
0# 变量i为整数5,用match匹配整数格式,返回1(匹配成功,1表示匹配的长度)
[bq@shell ~]$ i=5
[bq@shell ~]$ expr match "$i" "^[0-9][0-9]*$"  # ^[0-9][0-9]*$:匹配0或非0开头的整数(包括0)
1

示例 2:判断文件扩展名是否符合要求

通过 expr "$变量" : "正则表达式" 匹配字符串,若返回值大于 0 则匹配成功,否则失败。

# 定义文件名为stu-202212.jpg(扩展名是jpg)
[bq@shell ~]$ file=stu-202212.jpg# 用正则表达式".*\.jpg$"匹配以.jpg结尾的文件(.*匹配任意字符,\.jpg$匹配.jpg结尾)
# 返回值14表示匹配的字符串长度(整个文件名长度),说明匹配成功
[bq@shell ~]$ expr "$file" : ".*\.jpg$"
14# 查看返回值(0表示成功)
[bq@shell ~]$ echo $?
0# 用正则表达式".*\.pub$"匹配以.pub结尾的文件(当前文件不匹配)
# 返回值0表示未匹配
[bq@shell ~]$ expr "$file" : ".*\.pub$"
0# 查看返回值(1表示失败)
[bq@shell ~]$ echo $?
1

示例 3:计算字符串的长度

expr length "字符串" 可直接获取字符串的长度(字符个数)。

# 定义字符串str为"abc123abc123"
[bq@shell ~]$ str="abc123abc123"# 计算str的长度(a、b、c、1、2、3、a、b、c、1、2、3共12个字符)
[bq@shell ~]$ expr length "$str"
12

示例 4:打印字符数不大于 6 的单词

脚本功能:遍历字符串中的每个单词,用 expr length 计算单词长度,筛选出长度≤6 的单词并输出。

#!/bin/bash
# 定义要处理的字符串(包含多个单词)
strings="This is Linux World  Welcome to our classroom"# 遍历字符串中的每个单词(for循环默认按空格分割)
for word in $strings
do# 用expr length计算单词长度,若长度≤6则输出该单词if [ $(expr length "$word") -le 6 ];thenecho $wordfi
done

执行验证

# 执行脚本
[bq@shell ~]$ bash str.sh
This  # 长度4(≤6)
is    # 长度2(≤6)
Linux # 长度5(≤6)
World # 长度5(≤6)
to    # 长度2(≤6)
our   # 长度3(≤6)

说明:字符串中的单词长度分别为:This(4)、is(2)、Linux(5)、World(5)、Welcome(7,不输出)、to(2)、our(3)、classroom(10,不输出),因此输出符合条件的单词。

bc 命令

bc 是 Linux 自带的计算器程序,支持整数和小数运算,还可以通过 scale 控制小数位数。

实验流程:通过交互式和非交互式两种方式使用 bc,演示整数、小数运算及小数位数控制。

示例

# 进入bc交互式模式(输入bc后回车)
[bq@shell ~]$ bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. # 计算复杂表达式1+3*4-6/3^3%4(3^3=27,6/27=0,0%4=0,所以1+12-0=13)
1+3*4-6/3^3%4
13# 设置小数位数为4(scale控制小数位数)
scale=4# 计算1/3,结果保留4位小数
1/3
.3333# 退出bc交互式模式
quit# 非交互式模式:用echo将表达式传给bc,计算结果并输出
[bq@shell ~]$ echo '1+3*4-6/3^3%4' | bc
13# 非交互式模式:设置scale=4后计算1/3,结果保留4位小数
[bq@shell ~]$ echo 'scale=4;1/3' | bc
.3333

awk 命令实现计算

awk 是一种文本处理工具,同时也支持数值运算,尤其适合小数计算,精度较高。

实验流程:通过两个示例演示 awk 处理小数和整数运算的能力。

示例

# 用echo传递两个小数7.7和3.8给awk,计算它们的差(7.7-3.8=3.9)
[bq@shell ~]$ echo 7.7 3.8 | awk '{ print $1-$2 }'  # $1表示第一个参数,$2表示第二个参数
3.9# 传递两个整数358和113给awk,计算(358-3)/113的结果(355/113≈3.14159)
[bq@shell ~]$ echo 358 113 | awk '{ print ($1-3)/$2 }'
3.14159

$[] 符号的运算

$[] 是 Shell 中用于整数运算的符号,语法简单,用法和 $(()) 类似。

实验流程:通过多个示例演示 $[] 的基本运算、变量参与运算及自增自减操作。

示例 1:基本运算

# 计算1+1的结果并输出
[bq@shell ~]$ echo $[1+1]
2# 计算4-2的结果并输出
[bq@shell ~]$ echo $[4-2]
2# 计算2*2的结果并输出
[bq@shell ~]$ echo $[2*2]
4# 计算4/2的结果并输出(整数除法,结果取整)
[bq@shell ~]$ echo $[4/2]
2# 计算5/2的结果并输出(5÷2=2.5,取整为2)
[bq@shell ~]$ echo $[5/2]
2# 计算5%2的结果并输出(5除以2的余数是1)
[bq@shell ~]$ echo $[5%2]
1# 定义count=3,计算(count+1)*3的结果((3+1)*3=12)
[bq@shell ~]$ count=3;echo $[(count+1)*3]
12# 前置自增:先将count加1(3+1=4),再计算4+3=7
[bq@shell ~]$ count=3;echo $[ ++count + 3 ]
7# 后置自增:先计算3+3=6,再将count加1(此时count=4)
[bq@shell ~]$ count=3;echo $[ count++ + 3 ]
6# 前置自减:先将count减1(3-1=2),再计算2+3=5
[bq@shell ~]$ count=3;echo $[ --count + 3 ]
5# 后置自减:先计算3+3=6,再将count减1(此时count=2)
[bq@shell ~]$ count=3;echo $[ count-- + 3 ]
6

示例 2:计算 1 到 10 的和并输出表达式及结果

要求:输出格式为 1+2+3+...+10=55

# 方法1:用seq -s "+" 10生成"1+2+...+10",通过bc计算结果,再用echo拼接
[bq@shell ~]$ echo "$(seq -s + 10)=$(seq -s + 10 | bc)"
1+2+3+4+5+6+7+8+9+10=55# 方法2:用{1..10}生成1到10,tr将空格转为+,再用$((...))计算结果
[bq@shell ~]$ echo "$(echo {1..10} | tr ' ' '+')=$(( $(echo {1..10} | tr ' ' '+' ) ))"
1+2+3+4+5+6+7+8+9+10=55# 方法3:用$[]计算结果,其余和方法2相同
[bq@shell ~]$ echo "$(echo {1..10} | tr ' ' '+')=$[ $(echo {1..10} | tr ' ' '+' ) ]"
1+2+3+4+5+6+7+8+9+10=55

验证说明:三种方法均能生成 1+2+...+10 的表达式,并计算出和为 55,符合预期结果。

如涉及版权问题,请联系作者处理!!!

http://www.dtcms.com/a/347749.html

相关文章:

  • python re模块常用方法
  • 取件码-快递取件助手, 短信自动识别ios app Tech Support
  • Access开发打造专业的开关按钮效果
  • rust语言 (1.88) egui (0.32.1) 学习笔记(逐行注释)(七) 鼠标在控件上悬浮时的提示
  • Meta押注Midjourney:一场关于生成式AI的加速赛
  • 【读代码】SQLBot:开源自然语言转SQL智能助手原理与实践
  • GUAVA 实现限流
  • GEO优化服务商赋能全球数字经济发展 技术创新引领行业新格局
  • Java—— 动态代理
  • 基于Python与Tkinter的校园点餐系统设计与实现
  • Spring Data Redis基础
  • [Vid-LLM] docs | 视频理解任务
  • Windows应急响应一般思路(三)
  • 第1.2节:早期AI发展(1950-1980)
  • 老字号:用 “老根” 熬活的 “新味道”
  • redis---string类型详解
  • 大模型四种常见安全问题与攻击案例
  • mysql的mvcc
  • 大语言模型应用开发——利用OpenAI函数与LangChain结合从文本构建知识图谱搭建RAG应用全流程
  • Redis全面详解:从配置入门到实战应用
  • 【前端debug调试】
  • 【Java SE】抽象类、接口与Object类
  • 从“一指禅”到盲打:如何系统提升电脑输入能力?
  • 25.深入对象
  • 联邦学习之----联邦批量归一化(FedBN)
  • 线程间Bug检测工具Canary
  • Python字符串
  • SOC估算方法-蜣螂优化算法结合极限学习
  • 1200 SCL学习笔记
  • 机器人控制基础:串级PID控制算法的参数如何整定?