bash编程_如何使用Bash编程:循环

bash编程

Bash是一种强大的编程语言,一种完美设计用于命令行和Shell脚本的语言。 这个由三部分组成的系列基于我的三卷Linux自学课程 ,探讨了在命令行界面(CLI)上使用Bash作为编程语言。

本系列的第一篇文章探讨了一些使用Bash的简单命令行编程,包括使用变量和控件运算符。 第二篇文章探讨了文件,字符串,数字和其他逻辑运算符的类型,这些运算符在Bash中提供了执行流控制逻辑和不同类型的Shell扩展。 第三篇(也是最后一篇)文章探讨了使用循环执行各种类型的迭代操作以及控制这些循环的方法。

循环

我曾经使用过的每种编程语言都至少具有两种循环结构,这些循环结构提供了执行重复操作的各种功能。 我经常使用for循环,但是我也发现while和until循环很有用。

for循环

我认为Bash for命令的实现比大多数实现灵活一些,因为它可以处理非数字值。 相反,例如,标准的C语言for循环只能处理数字值。

Bash版本的for命令的基本结构很简单:

 for Var in list1 ; do list2 ; done 

转换为:“对于list1中的每个值,将$ Var设置为该值,然后使用该值执行list2中的程序语句;使用完list1中的所有值后,它就完成了,因此退出循环。 ” list1中的值可以是一个简单的显式值字符串,也可以是命令替换的结果(在系列的第二篇文章中进行了介绍)。 我经常使用这种结构。

要尝试它,请确保〜/ testdir仍然是当前的工作目录(PWD)。 清理目录,然后看一个for循环的简单示例,从一个明确的值列表开始。 该列表混合了字母数字值-但不要忘记所有变量都是字符串,因此可以将其视为字符串。


   
   
[ student @ studentvm1 testdir ] $ rm *
[ student @ studentvm1 testdir ] $ for I in a b c d 1 2 3 4 ; do echo $I ; done
a
b
c
d
1
2
3
4

这是一个更有用的版本,具有更有意义的变量名称:


   
   
[ student @ studentvm1 testdir ] $ for Dept in "Human Resources" Sales Finance "Information Technology" Engineering Administration Research ; do echo "Department $Dept " ; done
Department Human Resources
Department Sales
Department Finance
Department Information Technology
Department Engineering
Department Administration
Department Research

创建一些目录(并在此过程中显示一些进度信息):


   
   
[ student @ studentvm1 testdir ] $ for Dept in "Human Resources" Sales Finance "Information Technology" Engineering Administration Research ; do echo "Working on Department $Dept " ; mkdir " $Dept "  ; done
Working on Department Human Resources
Working on Department Sales
Working on Department Finance
Working on Department Information Technology
Working on Department Engineering
Working on Department Administration
Working on Department Research
[ student @ studentvm1 testdir ] $ ll
total 28
drwxrwxr-x 2 student student 4096 Apr   8 15 : 45  Administration
drwxrwxr-x 2 student student 4096 Apr   8 15 : 45  Engineering
drwxrwxr-x 2 student student 4096 Apr   8 15 : 45  Finance
drwxrwxr-x 2 student student 4096 Apr   8 15 : 45 'Human Resources'
drwxrwxr-x 2 student student 4096 Apr   8 15 : 45 'Information Technology'
drwxrwxr-x 2 student student 4096 Apr   8 15 : 45  Research
drwxrwxr-x 2 student student 4096 Apr   8 15 : 45  Sales

$ Dept变量必须在mkdir语句中用引号引起来; 否则,由两部分组成的部门名称(例如“信息技术”)将被视为两个单独的部门。 这突出了我要遵循的最佳实践:所有文件和目录名称都应该是一个单词。 尽管大多数现代操作系统都可以使用名称来处理空格,但是sysadmin仍需要进行额外的工作才能确保在脚本和CLI程序中考虑这些特殊情况。 (即使它们很烦人,也几乎应该考虑考虑它们,因为您永远不知道将拥有哪些文件。)

因此,再次删除〜/ testdir中的所有内容,然后再执行一次:


   
   
[ student @ studentvm1 testdir ] $ rm -rf * ; ll
total 0
[ student @ studentvm1 testdir ] $ for Dept in Human-Resources Sales Finance Information-Technology Engineering Administration Research ; do echo "Working on Department $Dept " ; mkdir " $Dept "  ; done
Working on Department Human-Resources
Working on Department Sales
Working on Department Finance
Working on Department Information-Technology
Working on Department Engineering
Working on Department Administration
Working on Department Research
[ student @ studentvm1 testdir ] $ ll
total 28
drwxrwxr-x 2 student student 4096 Apr   8 15 : 52 Administration
drwxrwxr-x 2 student student 4096 Apr   8 15 : 52 Engineering
drwxrwxr-x 2 student student 4096 Apr   8 15 : 52 Finance
drwxrwxr-x 2 student student 4096 Apr   8 15 : 52 Human-Resources
drwxrwxr-x 2 student student 4096 Apr   8 15 : 52 Information-Technology
drwxrwxr-x 2 student student 4096 Apr   8 15 : 52 Research
drwxrwxr-x 2 student student 4096 Apr   8 15 : 52 Sales

假设有人要求提供特定Linux计算机上所有RPM的列表以及每一个的简短描述。 当我在北卡罗来纳州工作时,这发生在我身上。 由于当时开放源代码尚未得到国家机构的“批准”,而且我仅在台式机上使用Linux,因此尖头的老板(PHB)需要列出计算机上已安装的每个软件的清单,因此他们可以“批准”一个例外。

您将如何处理? 这是一种方法,首先要知道rpm –qa命令提供了RPM的完整描述,包括PHB想要的两项:软件名称和简要说明。

一次一步建立最终结果。 首先,列出所有RPM:


   
   
[ student @ studentvm1 testdir ] $ rpm -qa
perl-HTTP-Message- 6.18 - 3 .fc29.noarch
perl-IO- 1.39 - 427 .fc29.x86_64
perl-Math-Complex- 1.59 - 429 .fc29.noarch
lua-5.3.5- 2 .fc29.x86_64
java- 11 -openjdk-headless- 11.0 .ea.28- 2 .fc29.x86_64
util-linux-2.32.1- 1 .fc29.x86_64
libreport-fedora-2.9.7- 1 .fc29.x86_64
rpcbind-1.2.5- 0 .fc29.x86_64
libsss_sudo-2.0.0- 5 .fc29.x86_64
libfontenc-1.1.3- 9 .fc29.x86_64
< snip >

添加sortuniq命令对列表进行排序并打印唯一的列表(因为可能安装了一些具有相同名称的RPM):


   
   
[ student @ studentvm1 testdir ] $ rpm -qa | sort | uniq
a2ps- 4.14 - 39 .fc29.x86_64
aajohan-comfortaa-fonts- 3.001 - 3 .fc29.noarch
abattis-cantarell-fonts- 0.111 - 1 .fc29.noarch
abiword-3.0.2- 13 .fc29.x86_64
abrt-2.11.0- 1 .fc29.x86_64
abrt-addon-ccpp-2.11.0- 1 .fc29.x86_64
abrt-addon-coredump-helper-2.11.0- 1 .fc29.x86_64
abrt-addon-kerneloops-2.11.0- 1 .fc29.x86_64
abrt-addon-pstoreoops-2.11.0- 1 .fc29.x86_64
abrt-addon-vmcore-2.11.0- 1 .fc29.x86_64
< snip >

由于这给出了您要查看的RPM的正确列表,因此可以将其用作循环的输入列表,该循环将打印每个RPM的所有详细信息:

 [ student @ studentvm1 testdir ] $ for RPM in ` rpm -qa | sort | uniq ` ; do rpm -qi $RPM ; done 

此代码产生的数据比您想要的更多。 请注意,循环已完成。 下一步是仅提取PHB请求的信息。 因此,添加一个egrep命令,该命令用于选择^ Name^ Summary 。 克拉( ^ )指定行的开头; 因此,将显示任何在行首带有“名称”或“摘要”的行。


   
   
[ student @ studentvm1 testdir ] $ for RPM in ` rpm -qa | sort | uniq ` ; do rpm -qi $RPM ; done | egrep -i "^Name|^Summary"
Name        : a2ps
Summary     : Converts text and other types of files to PostScript
Name        : aajohan-comfortaa-fonts
Summary     : Modern style true type font
Name        : abattis-cantarell-fonts
Summary     : Humanist sans serif font
Name        : abiword
Summary     : Word processing program
Name        : abrt
Summary     : Automatic bug detection and reporting tool
< snip >

您可以在上面的命令中尝试使用grep而不是egrep ,但是它将不起作用。 您还可以通过less过滤器将此命令的输出通过管道传递,以浏览结果。 最终的命令序列如下所示:

 [ student @ studentvm1 testdir ] $ for RPM in ` rpm -qa | sort | uniq ` ; do rpm -qi $RPM ; done | egrep -i "^Name|^Summary" > RPM-summary.txt 

此命令行程序在单个行上使用管道,重定向和for循环。 它将小CLI程序的输出重定向到一个文件,该文件可以在电子邮件中使用或用作其他目的的输入。

一次只构建一个程序的过程使您可以查看每个步骤的结果,并确保它按预期工作并提供所需的结果。

通过此练习,PHB收到了1900多个单独的RPM软件包的列表。 我严重怀疑有人会阅读该列表。 但是我完全按照他们的要求给了他们,我再也没有听到他们的话了。

其他循环

Bash中还有两种可用的循环结构类型: whileuntil结构,它们在语法和功能上都非常相似。 这些循环结构的基本语法很简单:

 while [ expression ] ; do list ; done 

 until [ expression ] ; do list ; done 

第一个逻辑是:“当表达式的值为真时,执行程序语句列表。当表达式的值为假时,退出循环。” 第二个:“直到表达式的值为真,才执行程序语句列表。当表达式的值为真时,退出循环。”

While循环

while循环用于执行一系列程序语句,而(只要)逻辑表达式的值为真。 您的PWD应该仍然是〜/ testdir

while循环的最简单形式是永远运行的形式。 以下形式使用true语句始终生成“ true”返回码。 您还可以使用一个简单的“ 1”(它的工作原理相同),但这说明了使用true语句:


   
   
[ student @ studentvm1 testdir ] $ X = 0 ; while [ true ] ; do echo $X ; X =$ ( ( X+ 1 ) ) ; done | head
0
1
2
3
4
5
6
7
8
9
[ student @ studentvm1 testdir ] $

既然您已经研究了它的各个部分,那么该CLI程序应该更有意义。 首先,将$ X设置为零,以防它有上一个程序或CLI命令留下的值。 然后,由于逻辑表达式[true]始终求值为1,即为true,因此将永久执行dodone之间的程序指令列表,或者直到您按Ctrl + C或向程序发送信号2为止。 这些指令是算术扩展,将打印$ X的当前值,然后将其递增1。

Sysadmin的Linux哲学的宗旨之一是追求优雅,而实现优雅的一种方法是简单。 您可以使用变量增量运算符++简化此程序。 在第一种情况下,将打印变量的当前值,然后将变量递增。 通过在变量后放置++运算符来表明这一点:


   
   
[ student @ studentvm1 ~ ] $ X = 0 ; while [ true ] ; do echo $ ( ( X++ ) ) ; done | head
0
1
2
3
4
5
6
7
8
9

现在删除| 从节目的最后 ,再次运行。

在此版本中,变量在打印其值之前先增加。 这是通过将++运算符放在变量之前来指定的。 你能看到差别吗?


   
   
[ student @ studentvm1 ~ ] $ X = 0 ; while [ true ] ; do echo $ ( ( ++X ) ) ; done | head
1
2
3
4
5
6
7
8
9

您已将两个语句简化为一个语句,该语句将输出变量的值并递增该值。 还有一个减量运算符-

您需要一种用于以特定数量停止循环的方法。 为此,请将真实表达式更改为实际的数字求值表达式。 使程序循环到5并停止。 在下面的示例代码中,您可以看到-le是“小于或等于”的逻辑数字运算符。 这意味着:“只要$ X小于或等于5,循环就会继续。当$ X增至6时,循环终止。”


   
   
[ student @ studentvm1 ~ ] $ X = 0 ; while [ $X -le 5 ] ; do echo $ ( ( X++ ) ) ; done
0
1
2
3
4
5
[ student @ studentvm1 ~ ] $

直到循环

直到命令非常类似于while命令。 区别在于它将继续循环,直到逻辑表达式的值为“ true”为止。 查看此构造的最简单形式:


   
   
[ student @ studentvm1 ~ ] $ X = 0 ; until false  ; do echo $ ( ( X++ ) ) ; done | head
0
1
2
3
4
5
6
7
8
9
[ student @ studentvm1 ~ ] $

它使用逻辑比较来计数到特定值:


   
   
[ student @ studentvm1 ~ ] $ X = 0 ; until [ $X -eq 5 ]  ; do echo $ ( ( X++ ) ) ; done
0
1
2
3
4
[ student @ studentvm1 ~ ] $ X = 0 ; until [ $X -eq 5 ]  ; do echo $ ( ( ++X ) ) ; done
1
2
3
4
5
[ student @ studentvm1 ~ ] $

摘要

本系列探讨了许多用于构建Bash命令行程序和Shell脚本的强大工具。 但是,它几乎没有触及您可以使用Bash进行的许多有趣操作的表面。 其余的取决于您。

我发现学习Bash编程的最好方法就是做到这一点。 查找一个需要多个Bash命令的简单项目,并使用它们制作一个CLI程序。 系统管理员会执行许多任务,使其适合CLI编程,因此,我相信您会轻松地找到要自动化的任务。

许多年前,尽管熟悉其他Shell语言和Perl,但我还是决定将Bash用于所有系统管理员自动化任务。 我发现(有时需要进行一些搜索)我已经能够使用Bash完成我需要的一切。

翻译自: https://opensource.com/article/19/10/programming-bash-loops

bash编程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值