【Linux】shell 脚本进阶(三)

简介: 【Linux】shell 脚本进阶(三)

正文


1、for 命令


bash shell 提供了 for 命令,允许你创建一个遍历一系列值的循环。每次迭代都使用其中一个值来执行已定义好的一组命令,


for var in list
do
    command
done


在 list 参数中,你需要提供迭代中需要用到的一系列值,

  • 在每次迭代中,变量 var 会包含列表中的当前值。第一次迭代会使用列表中的第一个值,第二次迭代使用第二个值,以此类推,知道列表中的所有值都过一遍,
  • 在 do 和 done 语句之间输入的命令可以是一条或多条标准的 bash shell 命令。在这些命令中,$var 变量包含着这次迭代对应的当前列表项中的值。


1.1 读取列表中的值


for 命令最基本的用法就是遍历 for 命令自身所定义的一系列值


#!/bin/bash
# Program:
#       basic for command
# History:
# 2021/12/18    junfenghe.cloud@qq.com  version:0.0.1
path=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export path
for test in Alabama Arizona Arkansas California Colorado
do
    echo "The next state is ${test}"
done
exit 0


3333.webp.jpg


1.2 读取列表中的复杂值


shell 看到了列表值中的单引号并尝试使用它们来定义一个单独的数据值,这真是把事情搞得一团糟。有两种方法可解决这个问题:

  • 使用转义字符(反斜线)来将单引号转移;
  • 使用双引号来定义用到单引号的值。


#!/bin/bash
# Program:
#       another example of how to use the for command
# History:
# 2021/12/18    junfenghe.cloud@q.com   version:0.0.1
path=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export path
for test in I don\'t know if "this'll" work
do
    echo "word: ${test}"
done
exit 0


3334.webp.jpg


1.3 从变量读取列表


通常 shell 脚本遇到的情况是,你将一系列值都集中存储在了一个变量中,然后需要遍历变量中的整个列表。


#!/bin/bash
# Program:
#       using a variable to hold the list
# History:
# 2021/12/18    junfenghe.cloud@qq.com  version:0.0.1
path=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export path
list="ALdjk djlsgkd dgskjn dsjgdkj dhn dsdsdn"
list=${list}" dingdsl"
for item in ${list}
do
    echo "Have you ever visited ${item}"
done
exit 0


334.webp.jpg


1.4 更改字段分隔符


内部字段分隔符(internal field separator),IFS 环境变量定义了 bash shell 用作字段分隔符的一系列字符。默认情况下,bash shell 会将下列字段当做字段分隔符,


  • 空格
  • 制表符
  • 换行符


776.webp.jpg

下面代码中所引文件的内容


#!/bin/bash
# Program:
#       reading values from a file
path=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export path
file="states"
IFS_OLD=${IFS}
IFS=$'\n'
for state in $(cat ${file})
do
    echo "Visit beautiful ${state}"
done
IFS=${IFS_OLD}
exit 0


777.webp.jpg


1.5 用通配符读取目录


可以用 for 命令来自动遍历目录中的文件。进行此操作时,必须在文件名或路径名中使用通配符。它会强制 shell 使用使用文件扩展匹配。文件扩展匹配是生成匹配指定通配符的文件名或路径名的过程。

在 Linux 中,目录名和文件名中包含空格当然是合法的。要适应这种情况,应该将变量用双引号圈起来。如果不这么做,遇到含有空格的目录名或文件名时就会有错误产生。


#!/bin/bash
# Program:
#       iterating through multiple directires
# History:
# 2021/12/18    junfenghe.cloud@qq.com  version:0.0.1
path=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export path
for file in /home/qij/.b*
do
    if [ -d "${file}" ]
    then
        echo "${file} is a directory"
    elif [ -f "${file}" ]
    then
        echo "${file} is a file"
    else
        echo "${file} does exist"
    fi
done
exit 0


777.webp.jpg

2、while 命令


1.1 while 的基本格式


while 的基本格式,


while test command
do
    other commands
done


#!/bin/bash
# Program:
#       while command test
# History:
# 2021/12/18    junfenghe.cloud@qq.com  version:0.0.1
path=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export path
val1=10
while [ ${val1} -gt 0 ]
do
    echo ${val1}
    (( val1=${val1} - 1 ))
done
exit 0

779.webp.jpg


3、until 命令


until 命令和 while 命令工作的方式完全相反。until 命令要求你指定一个通常返回非零退出状态码的测试命令。只有测试命令的退出状态码不为 0,bash shell 才会执行循环中列出的命令,一旦测试命令返回了退出状态 0,循环就结束了。


#!/bin/bash
# Program:
#       using the until command
# History:
# 2021/12/18    junfenghe.cloud@qq.com  version:0.0.1
path=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export path
val1=100
until [ ${val1} -eq 0 ]
do
    echo "${val1}"
    val1=$(( ${val1} - 25 ))
done
exit 0


77.webp.jpg


4、嵌套循环


循环语句可以在循环内使用任意类型的命令,包括其他循环命令。这种循环叫做嵌套循环(nested loop)。注意,在使用嵌套循环时,你是在迭代中使用迭代,与命令运行的次数是乘积关系。不注意这点的话,有可能会在脚本中造成问题。


#/bin/bash
# Program:
#       nesting for loops
# History:
# 2021/12/18    junfenghe.cloud@qq.com  version:0.0.1
path=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export path
for (( a = 1; a <= 3; a++ ))
do
    echo "Starting loop ${a}"
    for (( b = 1;b <=3; b++ ))
    do
        echo "    Inside loop: ${b}"
    done
done
exit 0


880.webp.jpg


#!/bin/bash
# Program:
#       placing a for loop inside a while loop
# History:
# 2021/12/18    junfenghe.cloud@qq.com  version:0.0.1
path=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export path
var1=5
while [ ${var1} -ge 0 ]
do
    echo "Outer loop: ${var1}"
    for (( var2 = 1; var2 < 3; var2++ ))
    do
        var3=$(( ${var1} * ${var2} ))
        echo "    Inside loop: ${var1} * ${var2} = ${var3}"
    done
    var1=$(( ${var1} - 1 ))
done
exit 0


664.webp.jpg

#!/bin/bash
# Program:
#       using until and while loops
path=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export path
var1=3
until [ ${var1} -eq 0 ]
do
    echo "Outer loop: ${var1}"
    var2=1
    while [ ${var2} -lt 5 ]
    do
        var3=$(echo "scale=4; ${var1} / ${var2}" | bc)
        echo "    Inner loop: ${var1} / ${var2} = ${var3}"
        var2=$(( ${var2} + 1 ))
    done
    var1=$(( ${var1} - 1 ))
done
exit 0


666.webp.jpg

5、循环处理文件数据


通常必须遍历存储在文件中的数据。这要求结合已经讲过的两种技术:

  • 使用嵌套循环
  • 修改 IFS 环境变量
    通过修改 IFS 环境变量,就能强制 for 命令将文件中的每行都当成一个条目来处理,即便数据中有空格也是如此。一旦从文件中提取出了单独的行,可能需要再次利用循环来提取行中的数据。


#!/bin/bash
# Program:
#       changing the IFS value
# History:
# 2021/12/18    junfenghe.cloud@qq.com  version:0.0.1
path=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export path
IFS.OLD=${IFS}
IFS=$'\n'
for entry in $( cat "/etc/passwd" )
do
    echo "Values in ${entry} -"
    IFS=:
    for value in ${entry}
    do
        echo "    ${value}"
    done
done
exit 0


345.webp.jpg


6、循环控制


6.1 break 命令


break 命令是退出循环的一个简单方法。可以用 break 命令来退出任意类型的循环,包括 while 和 until 循环。


#!/bin/bash
# Program:
#       breaking out of an outer loop
# History:
# 2021/12/18    junfenghe.cloud@qq.com  version:0.0.1
path=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export path
for (( a = 1; a < 4; a++ ))
do
    echo "Outer loop: ${a}"
    for (( b = 1; b < 100; b++ ))
    do
        if [ ${b} -gt 4 ]
        then
            break 2
        fi
        echo "    Inner loop: ${b}"
    done
done
exit 0


555.webp.jpg


PS: 上述代码里的 break n,其中 n 指定了要跳出的循环层数。默认情况下,为 1,表名跳出的是当前的循环。如果你将 n 设为 2,break 命令就会停止下一级的外部循环。


6.2 continue 命令


continue 命令可以提前中止某次循环中的命令,但并不会完全中止整个循环。可以在循环内部设置 shell 不执行命令的条件。


#!/bin/bash
# Program:
#       using the continue command
# History:
# 2021/12/18    junfenghe.cloud@qq.com  version:0.0.1
path=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export path
for (( var1 = 1; var1 < 15; var1++ ))
do
    if [ ${var1} -gt 5 ] && [ ${var1} -lt 10 ]
    then
        continue
    fi
    echo "Iteration number: ${var1}"
done
exit 0


556.webp.jpg


7、处理循环的输出


在 shell 脚本中,你可以对循环的输出使用管道或进行重定向。这可以通过在 done 命令之后添加一个处理命令来实现,


#!/bin/bash
# Program:
#       redirecting the for output to a file
# History:
# 2021/12/18    junfenghe.cloud@qq.com  version:0.0.1
path=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export path
for (( a = 1; a < 10; a++ ))
do
    echo "The number is ${a}"
done > test123.txt
echo "The command is finished."
exit 0


557.webp.jpg


以上算是我今天整整一天的简单练习、简书输出、工作输出的一部分。其实学到这里的时候,我工作中要编写的一键部署自动化脚本已经优化的差不多了,还剩一点,后面接着去解决。


(其实此间最有成就感的还是工作中要写的那个一键部署自动化脚本,百把来行 shell 脚本,感觉就是洋洋洒洒的非常帅气,就是不便发出来,只能内部用。)

目录
相关文章
|
2月前
|
Shell
一个用于添加/删除定时任务的shell脚本
一个用于添加/删除定时任务的shell脚本
88 1
|
3月前
|
Shell Linux
Linux shell编程学习笔记30:打造彩色的选项菜单
Linux shell编程学习笔记30:打造彩色的选项菜单
|
1月前
|
Shell Linux 测试技术
6种方法打造出色的Shell脚本
6种方法打造出色的Shell脚本
53 2
6种方法打造出色的Shell脚本
|
16天前
|
XML JSON 监控
Shell脚本要点和难点以及具体应用和优缺点介绍
Shell脚本在系统管理和自动化任务中扮演着重要角色。尽管存在调试困难、可读性差等问题,但其简洁高效、易于学习和强大的功能使其在许多场景中不可或缺。通过掌握Shell脚本的基本语法、常用命令和函数,并了解其优缺点,开发者可以编写出高效的脚本来完成各种任务,提高工作效率。希望本文能为您在Shell脚本编写和应用中提供有价值的参考和指导。
44 1
|
21天前
|
Ubuntu Shell 开发工具
ubuntu/debian shell 脚本自动配置 gitea git 仓库
这是一个自动配置 Gitea Git 仓库的 Shell 脚本,支持 Ubuntu 20+ 和 Debian 12+ 系统。脚本会创建必要的目录、下载并安装 Gitea,创建 Gitea 用户和服务,确保 Gitea 在系统启动时自动运行。用户可以选择从官方或小绿叶技术博客下载安装包。
41 2
|
27天前
|
Ubuntu Linux Shell
Linux 系统中的代码类型或脚本类型内容
在 Linux 系统中,代码类型多样,包括 Shell 脚本、配置文件、网络配置、命令行工具和 Cron 定时任务。这些代码类型广泛应用于系统管理、自动化操作、网络配置和定期任务,掌握它们能显著提高系统管理和开发的效率。
|
2月前
|
Web App开发 网络协议 Linux
linux命令总结(centos):shell常用命令汇总,平时用不到,用到就懵逼忘了,于是专门写了这篇论文,【便持续更新】
这篇文章是关于Linux命令的总结,涵盖了从基础操作到网络配置等多个方面的命令及其使用方法。
70 1
linux命令总结(centos):shell常用命令汇总,平时用不到,用到就懵逼忘了,于是专门写了这篇论文,【便持续更新】
|
2月前
|
监控 网络协议 Shell
ip和ip网段攻击拦截系统-绿叶结界防火墙系统shell脚本
这是一个名为“小绿叶技术博客扫段攻击拦截系统”的Bash脚本,用于监控和拦截TCP攻击。通过抓取网络数据包监控可疑IP,并利用iptables和firewalld防火墙规则对这些IP进行拦截。同时,该系统能够查询数据库中的白名单,确保合法IP不受影响。此外,它还具备日志记录功能,以便于后续分析和审计。
49 6
|
1月前
|
运维 监控 Shell
深入理解Linux系统下的Shell脚本编程
【10月更文挑战第24天】本文将深入浅出地介绍Linux系统中Shell脚本的基础知识和实用技巧,帮助读者从零开始学习编写Shell脚本。通过本文的学习,你将能够掌握Shell脚本的基本语法、变量使用、流程控制以及函数定义等核心概念,并学会如何将这些知识应用于实际问题解决中。文章还将展示几个实用的Shell脚本例子,以加深对知识点的理解和应用。无论你是运维人员还是软件开发者,这篇文章都将为你提供强大的Linux自动化工具。
|
2月前
|
运维 Java Linux
【运维基础知识】Linux服务器下手写启停Java程序脚本start.sh stop.sh及详细说明
### 启动Java程序脚本 `start.sh` 此脚本用于启动一个Java程序,设置JVM字符集为GBK,最大堆内存为3000M,并将程序的日志输出到`output.log`文件中,同时在后台运行。 ### 停止Java程序脚本 `stop.sh` 此脚本用于停止指定名称的服务(如`QuoteServer`),通过查找并终止该服务的Java进程,输出操作结果以确认是否成功。
46 1