Shell 编程快速入门 之 数学计算和函数基础

news2025/2/28 20:21:13

8c24851c4f9c4f6dbe0de1a3181800f5.png

目录

1. 求两数之和

整数之和

浮点数之和 

2. 计算1-100的和

for...in

C风格for循环

while...do

until...do

while和until的区别

关系运算符

break与continue的区别 

3. shell函数基础知识

函数定义 

函数名

函数体

参数

返回值

return返回值的含义

return与echo返回值的区别

4. 自定义库函数

定义库函数

调用库函数

执行结果

5. 递归函数

递归法实现阶乘函数

改用循环实现


1. 求两数之和

整数之和

shell程序的数字类型只有整数类型一种,并不支持浮点数。如:

hann@HannYang:~$ cat sum.sh
#!/bin/bash

# 读取第一个数
echo "请输入第一个数:"
read a

# 读取第二个数
echo "请输入第二个数:"
read b

# 计算两个数的和
sum=$(( a + b ))

# 输出结果
echo "这两个数的和为:$sum"
hann@HannYang:~$ bash sum.sh
请输入第一个数:
5
请输入第二个数:
3
这两个数的和为:8
hann@HannYang:~$

浮点数之和 

在shell编程中,浮点数只能被用作字符串来操作,脚本语法本身不提供浮点数的操作方法,但可以调用bc, awk等外部命令来计算并返回结果。如:

hann@HannYang:~$ cat sum2.sh
#!/bin/bash

num1=3.14
num2=2.72

# 计算和
sum=$(echo "$num1 + $num2" | bc)
echo "$num1 + $num2 = $sum"

sum=$(echo $num1 $num2 | awk '{print $1+$2}')
echo "$num1 + $num2 = $sum"
hann@HannYang:~$ bash sum2.sh
3.14 + 2.72 = 5.86
3.14 + 2.72 = 5.86

2. 计算1-100的和

用1~100累和的例子,示例循环结构的各种语句的写法:

for...in

hann@HannYang:~$ sum=0;for i in {1..100};do let sum+=i;done;echo $sum

C风格for循环

hann@HannYang:~$ sum=0;for ((i=1; i<=100; i++));do let sum+=i;done;echo $sum

while...do

sum=0  # 初始化变量sum为0
i=1  # 初始化计数器i为1
while [ $i -le 100 ]; do  # 当计数器i小于等于100时执行循环体
    let sum+=i  # 将当前整数累加到sum中
    i=$((i+1))  # 计数器自增1
done  # 结束循环
echo $sum  # 打印出变量sum的值

until...do

sum=0  # 初始化变量sum为0
i=1  # 初始化计数器i为1
until [ $i -gt 100 ]; do  # 当计数器i大于100时执行循环体
    let sum+=i  # 将当前整数累加到sum中
    i=$((i+1))  # 计数器自增1
done  # 结束循环
echo $sum  # 打印出变量sum的值

while和until的区别

while循环是当条件测试为真时执行,为假时退出循环
until循环是当条件测试为假时执行,为真时退出循环

while A; do 等价于 until not A; do
until A; do 等价于 while not A; do

while [ ! $i -gt 100 ]; do  <==> until [ $i -gt 100 ]; do
until [ ! $i -le 100 ]; do  <==> while [ $i -le 100 ]; do

关系运算符

-eq    equal 即 ==,检测两个数是否相等,相等返回 true。
-ne    not equal 即 !=,检测两个数是否不相等,不相等返回 true。
-gt    great than 即 >,检测左边的数是否大于右边的,如果是,则返回 true。
-lt     less than 即 <,检测左边的数是否小于右边的,如果是,则返回 true。
-ge    great equal 即>=,检测左边的数是否大于等于右边的,如果是,则返回 true。
-le    less equal,即<=,检测左边的数是否小于等于右边的,如果是,则返回 true。

break与continue的区别 

break语句用于退出本层循环,当执行到break会立即跳出当前循环,执行后续代码。
在多层嵌套循环中,break只会跳出最近的一层循环。

continue语句用于结束本次循环,跳过本次循环中剩余的代码,直接进入下一次循环。
在多层嵌套循环中,continue只会跳过最近的一层循环。

两种语句的基本用法与其它语言的基本一样,不另举例说明。

3. shell函数基础知识

函数定义 

函数名

Shell函数用关键字 function 声明,跟在后面的 name 即函数名。声明后就用"函数名 [参数]"来调用函数。function 非必须,也能用函数名加一对括号 name() { ... } 来声明定义函数。

函数体

函数名后的 { Commands; } 即函数体,是实现函数功能的主体。

参数

Shell函数可以通过参数接收输入的值。在函数定义时,可以在括号中指定参数列表。参数可以在函数体中使用,也可以通过特殊变量$#获取函数的参数个数,通过特殊变量$@获取所有的参数。

返回值

Shell函数可以有一个返回值,可以使用return语句返回一个值。返回值的范围是0到255之间,0表示成功,非零值表示错误。如果函数中没有return语句,或者使用exit命令退出函数,则函数的返回值为退出命令的返回值。

如一个计算2数之和的函数:

#!/bin/bash
function add() {
  local a=$1
  local b=$2
  local res=$((a + b))
  return $res
}

add 3 5
result=$?
echo "The result is: $result"

return返回值的含义

最后结果是从$?获取的,其实$?与其它语言中函数返回值是有区别 ,$? 本质上是返回上一条命令的退出状态,并且只是0~255间的整数,也就是最多返回256种状态。

除了$?还有另外4个特殊的变量,它们分别表示以下含义:

  • $$:表示当前Shell进程的进程ID(PID)。
  • $#:表示传递给脚本或函数的参数个数。
  • $@:表示以空格分隔的所有参数,将所有参数视为单个字符串。
  • $*:表示所有参数作为单独的字符串展开,每个参数之间用一个空格分隔。

例程:

hann@HannYang:~$ more sum3.sh
#!/bin/bash

function special_vars() {
  echo "Current PID \$: $$"
  echo "Number of arguments #: $#"
  echo "All arguments (as a single string) @: $@"
  echo "All arguments separated by spaces *: $*"
  echo
  return $(($1+$2+$3))
}

special_vars 1 2 3 4 5
echo "? = "$?
echo "\$ = "$$
echo "# = "$#
echo "@ = "$@
echo "* = "$*
hann@HannYang:~$ bash sum3.sh
Current PID $: 1679
Number of arguments #: 5
All arguments (as a single string) @: 1 2 3 4 5
All arguments separated by spaces *: 1 2 3 4 5

? = 6
$ = 1679
# = 0
@ =
* =

$?只能函数执行后调用,$#,$@,$*只能在函数内部调用,$$则在函数内外都能调用。

return与echo返回值的区别

为了显示两者的不通,echo后加了“sum=”,而return只能返回整数0~255。

例程:

#!/bin/bash
function add() {
  local a=$1
  local b=$2
  local res=$((a + b))
  echo sum=$res
  return $res
}

Result=$(add 100 155)
echo "The result is: $?"
echo "The result is: $Result"

Result=$(add 100 156)
echo "The result is: $?"
echo "The result is: $Result"

Result=$(add 155 358)
echo "The result is: $?"
echo "The result is: $Result"

echo "The result is: $(( (155+358)%256 ))"

输出:

The result is: 255
The result is: sum=255
The result is: 0
The result is: sum=256
The result is: 1
The result is: sum=513
The result is: 1

注意:

return 返回表达式的值,如溢出范围可以认为是 表达式与256相余的结果。

所以shell函多用echo来返回一个字串结果$res再进行调用,而return一般不会作函数值返回语句,它的真实用途是来返回程序运行状态的,比如:

例1:

hann@HannYang:~$ cat test.sh
#!/bin/bash

function filecount {
    # 检查目录是否存在
    if [ -d "$1" ]; then
        # 目录存在,计算文件数
        echo $(ls -l "$1" | grep "^-" | wc -l)
        return 1
    else
        # 目录不存在,返回0
        return 0
    fi
}

dir="$1"
count=$(filecount $dir)

if [ $? = 1 ]
then
    echo "Dir $dir exists,files:$count"
else
    echo "Dir $dir does'nt exist."
fi

dir="$2"
count=$(filecount $dir)

if [ $? = 0 ]
then
    echo "Dir $dir does'nt exist."
else
    echo "Dir $dir exists,files:$count"
fi
hann@HannYang:~$ bash test.sh rust golang
Dir rust exists,files:4
Dir golang does'nt exist.

例2:

hann@HannYang:~$ cat chkpid.sh
checkpid()
{
   #定义本地变量i
    local i

   #使用for循环遍历传递给此函数的所有参数
    for i in $*
    do
       #如果目录/proc/$i存在,则执行此函数返回0
       #在一般的Linux系统中,如果进程正在运行,则在/proc目录下会存在一个以进程号命名的子目录
       [ -d "/proc/$i" ] && return 0
    done

    #返回1
    return 1
}

#调用函数checkpid
checkpid $1 $2 $3

if [ $? = 0 ]
then
    echo "The one of them is running."
else
    echo "These PIDS are not running!"
fi
hann@HannYang:~$ bash chkpid.sh 866
The one of them is running.
hann@HannYang:~$ bash chkpid.sh 866 867 1882
The one of them is running.
hann@HannYang:~$ bash chkpid.sh 1882
These PIDS are not running!
hann@HannYang:~$ bash chkpid.sh 868 1882
These PIDS are not running!

可变参数函数

"$@"的应用: in $@表示遍历所有参数组成的“可迭代数组”。

示例:

#!/bin/bash

# 定义可变参数的函数
function sum4() {
  local sum=0
  for arg in "$@"
  do
    sum=$((sum + arg))
  done
  echo "The sum is: $sum"
}

# 调用函数并传递参数
sum4 10 20 30 50
sum4 1 2 3 4 5 6

输出:

The sum is: 110
The sum is: 21 

4. 自定义库函数

定义库函数

例:写一个函数库,如命名为 math_fun.sh 

function add
{
    echo "`expr $1 + $2`"
}

function sub
{
    echo "`expr $1 - $2`"
}

function mul
{
    echo "`expr $1 \* $2`"
}

function div
{
    if [ $2 = 0 ]; then
        return 0
    else
        echo "`expr $1 / $2`"
        return 1
    fi
}

调用库函数

在调用库文件的函数时,使用点符号“ . ” + 库函数文件名(指明文件的绝对路径、相对路径都行)进行调用。如 test_fun.sh :

#!/bin/bash
. math_fun.sh

add 10 20

sub 90 100

mul 5 6

div 100 25

div 0 100

div 100 0
if [ $? = 0 ];then
    echo "Error: divide by zero."
fi

执行结果

hann@HannYang:~$ bash test_fun.sh
30
-10
30
4
0
Error: divide by zero.

5. 递归函数

递归函数是一种在程序中调用自身的函数。在 Shell 编程中,也能使用递归函数来解决一些问题,例如计算阶乘、斐波那契数列等。

递归函数的实现需要满足以下两个条件:

  1. 函数必须有一个终止条件,否则会无限循环下去。
  2. 函数必须能够将问题分解成更小的问题,并且能够通过调用自身来解决这些小问题。

递归法实现阶乘函数

#!/bin/bash

factorial() {
    if [ $1 -le 1 ]
    then
        echo 1
    else
        echo $(( $1 * $(factorial $(( $1 - 1 ))) ))
    fi
}

read -p "请输入一个整数:" num
result=$(factorial $num)
echo "$num 的阶乘为 $result"

改用循环实现

#!/bin/bash

factorial() {
    local result=1
    for ((i=1; i<=$1; i++))
    do
        result=$((result * i))
    done
    echo $result
}

read -p "请输入一个整数:" num
result=$(factorial $num)
echo "$num 的阶乘为 $result"

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/915191.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023大数据专业建设解决方案

打造产教融合的就业育人综合服务平台。 随着大数据产业链与技术链的逐步成熟&#xff0c;整体人工智能岗位将从原来的以算法人才为主&#xff0c;开始转向以应用型人才与数字 蓝领人才为主&#xff0c;形成金字塔型人才结构。应用型本科与职业院校的学生也将逐渐在人工智能领域…

Docker(一) 安装Docker

一、安装 安装前置条件 yum install -y yum-utils device-mapper-persistent-data lvm2 更换数据源 yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 1、指定版本安装 yum list docker-ce --showduplicates | sort -r yum …

深入浅出理解卡尔曼滤波

重要说明&#xff1a;本文从网上资料整理而来&#xff0c;仅记录博主学习相关知识点的过程&#xff0c;侵删。 一、参考资料 我所理解的卡尔曼滤波 图说卡尔曼滤波&#xff0c;一份通俗易懂的教程 卡尔曼滤波简单分析 How a Kalman filter works, in pictures 说说卡尔曼滤波…

Java【手撕双指针】LeetCode 611. “有效三角形个数“, 图文详解思路分析 + 代码

文章目录 前言一、有效三角形个数1, 题目2, 思路分析1, 从左往右 or 从右往左?3, 代码展示 前言 各位读者好, 我是小陈, 这是我的个人主页, 希望我的专栏能够帮助到你: &#x1f4d5; JavaSE基础: 基础语法, 类和对象, 封装继承多态, 接口, 综合小练习图书管理系统等 &#x1…

一文了解Gin对Cookie的支持z

1. 引言 本文将从Web应用程序处理请求时需要用户信息&#xff0c;同时HTTP又是无状态协议这个矛盾点出发。从该问题出发&#xff0c;简单描述了解决该问题的Token 机制&#xff0c;进而引出Cookie的实现方案。 基于此我们将详细描述Cookie的规范&#xff0c;然后详细描述具体…

UE4如何连接dmx---摇头矩阵灯具的创建

UE4如何连接dmx---摇头矩阵灯具的创建 开始创建库&#xff01; 然后我们开始创建多少个灯珠&#xff08;注意了&#xff1a;这是矩阵灯&#xff0c;是看灯珠的&#xff09; 那么这里我们创建6X6灯珠 下面设置灯珠的属性&#xff0c;灯珠有什么属性呢&#xff0c;只有颜色属性&…

高忆管理:沪指震荡跌0.24%,医药、酿酒等板块走低,数据要素概念逆市活跃

22日早盘&#xff0c;两市股指高开低走&#xff0c;沪指盘中冲高回落&#xff0c;创业板指走势疲弱&#xff1b;北向资金净卖出超40亿元。 到午间收盘&#xff0c;沪指跌0.24%报3085.48点&#xff0c;深成指跌0.73%&#xff0c;创业板指跌1.3%&#xff1b;两市合计成交4510亿元…

Python 自定义装饰器与上下文管理

1、定义装饰器实现计算函数运行时间 # 自定义装饰器 def compute_time(func):def compute(*args, **kwargs):st time.time()result func(*args, **kwargs)et time.time()print(消费时间 %.6f s % (et - st))return resultreturn compute# 使用 compute_time def work(work_i…

(2018,解释可视化)GAN 解剖:可视化和理解生成对抗网络

GAN dissection: Visualizing and understanding generative adversarial networks 公众号&#xff1a;EDPJ 目录 0. 摘要 1. 简介 2. 相关工作 3. 方法 3.1 通过解剖表征单元 3.2 使用干预措施衡量因果关系 4. 结果 4.1 跨数据集、层和模型的单位比较 4.2 诊断和改…

VMware 使用U盘进入PE系统,下划线光标闪烁

一、前言 vmware虚拟机各种原因崩溃&#xff0c;然后又没有快照&#xff0c;怎么办&#xff1f; 或者 密码忘记了无法开机&#xff0c;这时候就想到使用PE了。 二、分析 但是使用U盘进入PE的时候&#xff0c;遇到了各种问题&#xff1a; 加载U盘修改启动顺序启动后出现下划线…

DiscuzQ 二开教程(7)——二次开发版本部署文档

DiscuzQ 二开教程&#xff08;7&#xff09;——二次开发版本部署文档 源码&#xff1a;Discuz-Q-V3: 本仓库为Discuz-Q V3.0.211111 版本的二次开发版本&#xff0c;是将DiscuzQ官方仓库进行合并代码&#xff08;All in One&#xff09;整理后的仓库&#xff0c;使用更方便。…

【2023年11月第四版教材】《第6章-项目管理概论》(合集篇)

《第6章-项目管理概论》 1 章节内容2 项目基础3 项目经理的角色3.1 项目经理的影响力范围3.2 项目经理领导力风格 4 价值驱动的项目管理知识体系4.1 开发生命周期类型 5 五大过程组6 五个过程组和十大知识领域 1 章节内容 【本章分值预测】大部分为新增内容&#xff0c;预计选…

ARL资产侦察灯塔 指纹增强

项目&#xff1a;https://github.com/loecho-sec/ARL-Finger-ADD 下载项目后运行 python3 ARl-Finger-ADD.py https://你的vpsIP:5003/ admin password该项目中的finger.json可以自己找到其他的指纹完善&#xff0c;然后运行脚本添加指纹。

微信开发之一键修改群聊备注的技术实现

修改群备注 修改群名备注后&#xff0c;如看到群备注未更改&#xff0c;是手机缓存问题&#xff0c;可以连续点击进入其他群&#xff0c;在点击进入修改的群&#xff0c;再返回即可看到修改后的群备注名&#xff0c;群名称的备注仅自己可见 请求URL&#xff1a; http://域名地…

Python采集电商平台泳衣数据进行可视化分析

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 环境使用: python 3.8 解释器 pycharm 编辑器 模块使用: 第三方模块 需要安装 requests —> 发送 HTTP请求 内置模块 不需要安装 csv —> 数据处理中经常会用到的一种文件格式 第三方模块安装&#xff1a…

高性能服务器Nodejs快速入门

目录 1 初识 Nodejs2 Buffer 缓冲区3 fs 文件系统模块3.1 读取文件3.2 写入文件3.3 路径动态拼接问题 __dirname3.4 其它操作 4 path 路径模块4.1 路径拼接 path.join()4.2 获取路径中文件名 path.basename()4.3 获取路径中文件扩展名 path.extname() 5 http 模块5.1 创建基本 …

2023年高教社杯数学建模思路 - 复盘:人力资源安排的最优化模型

文章目录 0 赛题思路1 描述2 问题概括3 建模过程3.1 边界说明3.2 符号约定3.3 分析3.4 模型建立3.5 模型求解 4 模型评价与推广5 实现代码 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 描述 …

Prompt本质解密及Evaluation实战(一)

一、基于evaluation的prompt使用解析 基于大模型的应用评估与传统应用程序的评估不太一样&#xff0c;特别是基于GPT系列或者生成式语言模型&#xff0c;因为模型生成的内容与传统意义上所说的内容或者标签不太一样。 以下是借用了ChatGPT官方的evaluation指南提出的对结果的具…

Http2.0协议深入解析

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

ChatGPT、Google Bard、Claude2、新BING哪一款人工智能聊天机器人适合自己

人工智能聊天机器人正在提高数无数专业人士的工作效率。下面我们就来看看目前最流行的几款强大的人工智能工具&#xff0c;以及它们具体如何帮助到你。 今年7月AI圈最大的动静之一便是AI初创公司Anthropic发布了其AI聊天机器人Claude最新版本——Claude2。该聊天机器人对标Open…