【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 脚本,感觉就是洋洋洒洒的非常帅气,就是不便发出来,只能内部用。)

目录
相关文章
|
1月前
|
存储 安全 Unix
七、Linux Shell 与脚本基础
别再一遍遍地敲重复的命令了,把它们写进Shell脚本,就能一键搞定。脚本本质上就是个存着一堆命令的文本文件,但要让它“活”起来,有几个关键点:文件开头最好用#!/usr/bin/env bash来指定解释器,并用chmod +x给它执行权限。执行时也有讲究:./script.sh是在一个新“房间”(子Shell)里跑,不影响你;而source script.sh是在当前“房间”里跑,适合用来加载环境变量和配置文件。
327 9
|
Ubuntu Linux 网络安全
Linux系统初始化脚本
一款支持Rocky、CentOS、Ubuntu、Debian、openEuler等主流Linux发行版的系统初始化Shell脚本,涵盖网络配置、主机名设置、镜像源更换、安全加固等多项功能,适配单/双网卡环境,支持UEFI引导,提供多版本下载与持续更新。
185 0
Linux系统初始化脚本
|
1月前
|
存储 Shell Linux
八、Linux Shell 脚本:变量与字符串
Shell脚本里的变量就像一个个贴着标签的“箱子”。装东西(赋值)时,=两边千万不能有空格。用单引号''装进去的东西会原封不动,用双引号""则会让里面的$变量先“变身”再装箱。默认箱子只能在当前“房间”(Shell进程)用,想让隔壁房间(子进程)也能看到,就得给箱子盖个export的“出口”戳。此外,Shell还自带了$?(上条命令的成绩单)和$1(别人递进来的第一个包裹)等许多特殊箱子,非常有用。
180 2
|
1月前
|
算法 Linux Shell
Linux实用技能:打包压缩、热键、Shell与权限管理
本文详解Linux打包压缩技巧、常用命令与原理,涵盖.zip与.tgz格式操作、跨系统传文件方法、Shell运行机制及权限管理,助你高效使用Linux系统。
Linux实用技能:打包压缩、热键、Shell与权限管理
|
4月前
|
Shell
Shell脚本循环控制:shift、continue、break、exit指令
使用这些命令可以让你的Shell脚本像有生命一样动起来。正确使用它们,你的脚本就能像一场精心编排的舞蹈剧目,既有旋律的起伏,也有节奏的跳跃,最终以一场惊艳的表演结束。每一个动作、每一个转折点,都准确、优雅地完成所需要表达的逻辑。如此,你的脚本不只是冰冷的代码,它透过终端的界面,跳着有节奏的舞蹈,走进观众——使用者的心中。
219 60
|
1月前
|
数据采集 监控 Shell
无需Python:Shell脚本如何成为你的自动化爬虫引擎?
Shell脚本利用curl/wget发起请求,结合文本处理工具构建轻量级爬虫,支持并行加速、定时任务、增量抓取及分布式部署。通过随机UA、异常重试等优化提升稳定性,适用于日志监控、价格追踪等场景。相比Python,具备启动快、资源占用低的优势,适合嵌入式或老旧服务器环境,复杂任务可结合Python实现混合编程。
|
3月前
|
Web App开发 缓存 安全
Linux一键清理系统垃圾:释放30GB空间的Shell脚本实战​
这篇博客介绍了一个实用的Linux系统盘清理脚本,主要功能包括: 安全权限检查和旧内核清理,保留当前使用内核 7天以上日志文件清理和系统日志压缩 浏览器缓存(Chrome/Firefox)、APT缓存、临时文件清理 智能清理Snap旧版本和Docker无用数据 提供磁盘空间使用前后对比和大文件查找功能 脚本采用交互式设计确保安全性,适合定期维护开发环境、服务器和个人电脑。文章详细解析了脚本的关键功能代码,并给出了使用建议。完整脚本已开源,用户可根据需求自定义调整清理策略。
389 1
|
5月前
|
Java Linux
自定义linux脚本用于快速jar包启动、停止、重启
自定义linux脚本用于快速jar包启动、停止、重启
291 29
|
5月前
|
存储 Unix Shell
确定Shell脚本在操作系统中的具体位置方法。
这对于掌握Linux的文件系统组织结构和路径方面的理解很有帮助,是我们日常工作和学习中都可能使用到的知识。以上讲解详细清晰,应用简便,是每一个想要精通操作系统的计算机爱好者必备的实用技能。
131 17
|
5月前
|
Linux Shell 数据安全/隐私保护
Centos或Linux编写一键式Shell脚本创建用户、组、目录分配权限指导手册
Centos或Linux编写一键式Shell脚本创建用户、组、目录分配权限指导手册
319 3
下一篇
开通oss服务