linux从0到1——shell编程8

news/2024/11/23 10:06:49/

声明! 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他均与本人以及泷羽sec团队无关,切勿触碰法律底线,否则后果自负!!!!有兴趣的小伙伴可以点击下面连接进入b站主页[B站泷羽sec](https://space.bilibili.com/350329294)

在 Shell 编程中,until 循环是与 while 循环相反的一种循环结构。until 循环会在条件为 时执行循环体,直到条件变为 时停止循环。

until 循环的语法

until [ condition ]
do
  # 循环体
done

  • [ condition ]:是循环的判断条件,Shell 会在每次循环之前检查该条件。只要条件为假(返回非零值),循环就会继续执行。
  • dodone:标记循环体的开始和结束。

until 循环的工作原理

  • 在每次迭代之前,Shell 会检查条件是否为真(返回状态码为 0)。如果条件为 (返回状态码非 0),则执行循环体内的代码。
  • 当条件变为 (返回状态码为 0)时,until 循环结束。

示例 1:基本的 until 循环

以下示例展示了如何使用 until 循环打印从 1 到 5 的数字:

#!/bin/bash

i=1
until [ $i -gt 5 ]  # 条件是:i 小于或等于 5 时循环
do
  echo $i
  ((i++))  # 自增 i 的值
done

解释:

  • 变量 i 被初始化为 1。
  • 循环的条件 [ $i -gt 5 ] 只有当 i 大于 5 时才为真,此时循环结束。
  • 每次循环,echo $i 会打印当前的 i 值,然后通过 ((i++)) 将 i 增加 1。

输出:

示例 2:条件为假时继续执行

until 循环会一直执行,直到条件变为真。如果条件最初是 ,那么循环会立即开始执行。

#!/bin/bash

count=1
until [ $count -gt 10 ]
do
  echo "Count is $count"
  ((count++))  # 自增 count
done

解释:

  • 该循环会打印从 1 到 10 的值。
  • 条件 [ $count -gt 10 ] 判断 count 是否大于 10,只有当 count 大于 10 时,循环才会结束。
  • 循环体内,count 每次都会递增。

输出:

示例 3:使用 break 跳出循环

你可以使用 break 来提前终止 until 循环。

#!/bin/bash

count=1
until [ $count -gt 10 ]
do
  if [ $count -eq 5 ]; then
    echo "Reached 5, breaking out of loop"
    break  # 条件为 5 时跳出循环
  fi
  echo "Count is $count"
  ((count++))
done

解释:

  • 当 count 等于 5 时,break 会终止循环。
  • 其余部分正常打印 count 值。

输出:

示例 4:使用 continue 跳过当前循环

continue 用来跳过当前循环的剩余部分,直接进入下一次循环。

#!/bin/bash

count=1
until [ $count -gt 5 ]
do
  ((count++))
  if [ $count -eq 3 ]; then
    continue  # 当count等于3时,跳过当前循环
  fi
  echo "Count is $count"
done

解释:

  • 当 count 等于 3 时,continue 会跳过 echo 语句,直接进入下一次循环。
  • 因此,3 不会被打印。

输出:

until 和 while 的对比

until 循环与 while 循环有相似之处,但它们的行为是相反的:

  • while 循环:当条件为 (返回状态码为 0)时继续执行。
  • until 循环:当条件为 (返回状态码非 0)时继续执行。

示例:相同功能的 until 和 while 循环

使用 while 循环:

#!/bin/bash

i=1
while [ $i -le 5 ]
do
  echo $i
  ((i++))
done

使用 until 循环:

#!/bin/bash

i=1
until [ $i -gt 5 ]
do
  echo $i
  ((i++))
done

这两个例子会产生相同的输出,因为它们都实现了相同的逻辑,只是条件判断的方式不同。

总结:

  • until 循环会在条件为 时执行循环体,直到条件为 时结束。
  • 可以结合 break 和 continue 控制循环的执行流程。
  • until 循环和 while 循环的区别在于条件判断的逻辑:until 继续执行直到条件变为真,while 继续执行直到条件为假。

case ... esac

case ... esac 为多选择语句,与其他语言中的 switch ... case 语句类似,是一种多分支选择结构,每个 case 分支用右圆括号开始,用两个分号 ;; 表示 break,即执行结束,跳出整个 case ... esac 语句,esac(就是 case 反过来)作为结束标记。

可以用 case 语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。

case ... esac 语法格式如下:

casein
模式1)
    command1
    command2
    ...
    commandN
    ;;
模式
2)
    command1
    command2
    ...
    commandN
    ;;

esac

case 工作方式如上所示,取值后面必须为单词 in,每一模式必须以右括号结束。取值可以为变量或常数,匹配发现取值符合某一模式后,其间所有命令开始执行直至 ;;

取值将检测匹配的每一个模式。一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。如果无一匹配模式,使用星号 * 捕获该值,再执行后面的命令。

下面的脚本提示输入 1 到 4,与每一种模式进行匹配:

echo '输入 1 到 4 之间的数字:'

echo '你输入的数字为:'

read aNum

case $aNum in

    1)  echo '你选择了 1'

    ;;

    2)  echo '你选择了 2'

    ;;

    3)  echo '你选择了 3'

    ;;

    4)  echo '你选择了 4'

    ;;

    *)  echo '你没有输入 1 到 4 之间的数字'

    ;;

esac

跳出循环

在循环过程中,有时候需要在未达到循环结束条件时强制跳出循环,Shell 使用两个命令来实现该功能:break 和 continue

break 命令

break 命令允许跳出所有循环(终止执行后面的所有循环)。

下面的例子中,脚本进入死循环直至用户输入数字大于5。要跳出这个循环,返回到shell提示符下,需要使用break命令。

while :

do

    echo -n "输入 1 到 5 之间的数字:"

    read aNum

    case $aNum in

        1|2|3|4|5) echo "你输入的数字为 $aNum!"

        ;;

        *) echo "你输入的数字不是 1 到 5 之间的! 游戏结束"

            break

        ;;

    esac

done

 

continue

continue 命令与 break 命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。对上面的例子进行修改:

#!/bin/bash

while :

do

    echo -n "输入 1 到 5 之间的数字: "

    read aNum

    case $aNum in

        1|2|3|4|5) echo "你输入的数字为 $aNum!"

        ;;

        *) echo "你输入的数字不是 1 到 5 之间的!"

            continue

            echo "游戏结束"

        ;;

    esac

done

shell编程函数

在 Shell 编程中,函数是一个非常重要的构造,它允许你将一组命令封装到一个可重复使用的代码块中,以便在脚本中多次调用。Shell 函数可以帮助你提高代码的可维护性和重用性。

1. 函数的基本语法

Shell 函数的基本语法如下:

[ function ] funname [()]

{

    action;

    [return int;]

}

 

或者:

function_name() {
  # 函数体
}

  • function_name 是函数的名称。
  • 函数体是要执行的命令或语句。

2. 函数的定义与调用

示例 1:简单的函数定义与调用

#!/bin/bash

# 函数定义
greet() {
  echo "Hello, $1!"  # 使用传入的第一个参数
}

# 函数调用
greet "Alice"
greet "Bob"

解释:

  • greet 函数接收一个参数,并打印一个问候语。$1 是传递给函数的第一个参数。
  • greet "Alice" 会输出 Hello, Alice!,greet "Bob" 会输出 Hello, Bob!。

输出:

Hello, Alice!
Hello, Bob!

3. 函数中的参数

Shell 函数可以接收传递给它的参数。函数的参数由 $1、$2、$3 等表示,其中 $1 是第一个参数,$2 是第二个参数,依此类推。如果传入的参数超过 9 个,可以使用 ${10}、${11} 等来访问。

  • $0:脚本本身的名字
  • $1、$2、$3 等:传递给函数的第一个、第二个、第三个参数
  • $#:传递给函数的参数个数
  • $@:所有参数
  • $*:所有参数(与 $@ 相似,但处理方式略有不同)

示例 2:带参数的函数

#!/bin/bash

# 函数定义
add_numbers() {
  sum=$(( $1 + $2 ))  # 将两个参数相加
  echo "Sum: $sum"
}

# 函数调用
add_numbers 3 5
add_numbers 10 20

输出:

Sum: 8
Sum: 30

解释:

  • add_numbers 函数接收两个参数,使用 (( )) 进行加法运算,并输出结果。

4. 返回值

Shell 函数可以通过 return 语句返回一个值,但是 return 语句只支持返回一个整数值(通常用于返回状态码),而不能直接返回字符串或浮动值。如果需要返回多个值或更复杂的数据类型,通常会通过 echo 或将值保存在全局变量中来实现。

示例 3:使用 return 返回状态码

#!/bin/bash

# 函数定义
check_even_odd() {
  if (( $1 % 2 == 0 )); then
    return 0  # 返回 0 表示偶数
  else
    return 1  # 返回 1 表示奇数
  fi
}

# 函数调用
check_even_odd 4
if [ $? -eq 0 ]; then
  echo "The number is even."
else
  echo "The number is odd."
fi

check_even_odd 7
if [ $? -eq 0 ]; then
  echo "The number is even."
else
  echo "The number is odd."
fi

解释:

  • check_even_odd 函数判断一个数字是偶数还是奇数。
  • return 0 表示偶数,return 1 表示奇数。$? 可以获取上一个命令的返回值。

输出:

The number is even.
The number is odd.

示例 4:通过 echo 返回多个值

#!/bin/bash

# 函数定义
multiply_and_divide() {
  product=$(( $1 * $2 ))
  quotient=$(( $1 / $2 ))
  echo $product $quotient  # 通过 echo 返回多个值
}

# 函数调用
result=$(multiply_and_divide 6 3)
echo "Product and quotient: $result"

解释:

  • multiply_and_divide 函数通过 echo 返回两个值(乘积和商)。
  • 使用 $( ) 捕获函数的输出,将结果存储在 result 变量中。

输出:

Product and quotient: 18 2

5. 局部和全局变量

在 Shell 中,函数内部定义的变量是局部变量,默认情况下不会影响外部的变量。如果需要在函数外部访问或修改函数内的变量,通常使用 global 变量或通过 return 返回值。

示例 5:局部变量

#!/bin/bash

# 函数定义
increment() {
  local num=$1  # 使用 local 定义局部变量
  num=$(( num + 1 ))
  echo "Incremented value: $num"
}

# 函数调用
result=$(increment 5)
echo "Result after increment: $result"

解释:

  • local num=$1 在函数内部定义局部变量 num,确保该变量不会影响外部同名变量。

输出:

Incremented value: 6
Result after increment: 6

6. 函数递归

Shell 函数也支持递归,即函数在其内部调用自己。递归函数通常用来解决一些需要分解成相同子问题的问题。

示例 6:递归函数计算阶乘

#!/bin/bash

# 函数定义:递归计算阶乘
factorial() {
  if [ $1 -le 1 ]; then
    echo 1  # 基本条件
  else
    local result=$(( $1 * $(factorial $(( $1 - 1 )) ) ))  # 递归调用
    echo $result
  fi
}

# 函数调用
result=$(factorial 5)
echo "Factorial of 5: $result"

解释:

  • factorial 函数通过递归来计算阶乘。
  • 基本条件是当输入为 1 时,返回 1,其他情况下返回 n * (n-1)!。

输出:

Factorial of 5: 120

7. 函数最佳实践

  • 使用 local 关键字:局部变量可以防止函数修改全局变量,避免潜在的错误。
  • 避免全局变量冲突:尽量避免在函数中使用全局变量,特别是当多个函数使用相同变量时。
  • 合理使用递归:递归函数可以非常方便地解决问题,但需要小心避免栈溢出和确保基本条件存在。

总结

  • 函数定义与调用: 使用 function_name() { } 来定义函数,通过 function_name 来调用。
  • 参数: 可以通过 $1、$2 等方式访问传递给函数的参数。
  • 返回值: 使用 return 返回状态码(整数),或者使用 echo 返回更复杂的值。
  • 局部变量: 使用 local 关键字来定义局部变量。
  • 递归: Shell 支持递归调用。

http://www.ppmy.cn/news/1549270.html

相关文章

React 表单Form 中的 useForm

1、介绍 useForm 是 React Hook Form 中的核心 Hook,用于管理表单的状态和行为。它提供了处理表单验证、数据收集、状态管理等功能的简便方法。useForm 本质上是用于创建和配置表单,并允许你在组件中与表单字段交互。 2、基本用法 useForm 是一个函数…

SQLite Having 子句

SQLite Having 子句 SQLite 是一种轻量级的数据库管理系统,广泛应用于移动设备和嵌入式系统。它支持标准的 SQL 语法,包括 SELECT 语句中的 HAVING 子句。HAVING 子句通常与 GROUP BY 子句一起使用,用于对分组后的结果进行条件过滤。 SQLit…

查找字符串中某个字符返回字符位置

当然有正则表达式就非常简单,没有的话也不用担心,我们自己写算法完成这个功能. 早期的vs版本不支持vs,当然也可以下载boost来实现,关键还是不想下载,那么就自己写吧. 1.要求,查找字符串中同一个字符,并找出字符的位置. 2.根据字符位置,计算出对应的x,y坐标. 算法第一步,查找字…

解决前后端发版本时候,手动清除浏览器缓存

在.html页面中添加标签 后端配置nginx,让index.html不缓存 location /index.html { add_header Cache-Control “no-cache, no-store”; }在vite.config.ts中添加 rollupOpyions: { output: { // 输出编译后的文件名称:【文件名称.时间戳】、【文件名称.版本号.…

神经网络10-Temporal Fusion Transformer (TFT)

Temporal Fusion Transformer (TFT) 是一种专为时序数据建模而设计的深度学习模型,它结合了Transformer架构和其他技术,旨在有效地处理和预测时序数据中的复杂模式。TFT 于 2020 年由 Google Research 提出,旨在解决传统模型在时序预测中的一…

「Mac玩转仓颉内测版28」基础篇8 - 元组类型详解

本篇将介绍 Cangjie 中的元组类型,包括元组的定义、创建、访问、数据解构以及应用场景,帮助开发者掌握元组类型的使用。 关键词 元组类型定义元组创建元组访问数据解构应用场景 一、元组类型概述 在 Cangjie 中,元组是一种用于存储多种数据…

es执行_update_by_query要注意

背景: 一次给es新增字段,并且拷贝字段的操作,采用 curl -X POST "http://localhost:9200/xxx/_update_by_query" -H Content-Type: application/json -d {"script": {"source": "ctx._source.didstr c…

FIber + webWorker

文章目录 Fiber主要功能解决的问题如何解决 webworker 多线程作用使用注意点使用1 主线程3 Worker 加载脚本4 错误处理5 关闭 Worker 数据通信 Fiber 主要功能 为每个增加了优先级,优先级高的任务可以中断低优先级的任务。然后再重新执行优先级低的任务增加了异步…