《 Linux命令提示符》一书。 完整指南。 第二诠释 ed。”

图片 嗨,habrozhiteli! 国际畅销书“ Linux命令行”将帮助您克服从怯的按键击键到自信地为最新版本的bash(最受欢迎的Linux shell)创建完整程序的途径。 第二版讨论了bash 4.x中的新功能,例如新的重定向操作符和通配符操作。 您将学习永恒的命令行技能:导航文件系统,设置环境,链接命令以及与正则表达式匹配。 您将了解许多命令行工具背后的理念,了解从Unix超级计算机获得的丰富遗产,并了解几代专家的积累知识,他们将鼠标从工具库中排除了。 克服了第一个“外壳冲击”后,您将了解与计算机交互的方式是多么自然和合乎逻辑。

摘录。 Chapter 25.项目开始


在本章中,我们开始创建程序。 该项目的目的是展示如何使用Shell的各种功能来创建程序,最重要的是,创建好的程序。

接下来,我们将编写一个报告生成器 。 它将以HTML格式显示有关系统及其状态的各种信息,以便可以在Web浏览器中查看它。

通常,程序的创建是分几个阶段进行的,每个阶段都添加了新功能。 在第一阶段结束时,我们的程序将播放一个最小的HTML页面,不包含任何信息。 我们将在后续步骤中添加此信息。

第一阶段:最低文件数量


首先,让我们确定格式正确的HTML文档的格式。 它具有以下形式:

<html> <head> <title> </title> </head> <body>  . </body> </html> 

如果您在文本编辑器中输入此文本并将其保存在名为foo.html的文件中 ,我们可以通过在Firefox中输入以下URL来打开它: file:///home/username/foo.html
在第一阶段,我们将创建一个程序,将该HTML标记输出到标准输出。 编写这样的程序非常简单。 打开一个文本编辑器并创建一个名为〜/ bin / sys_info_page的文件:

 [me@linuxbox ~]$ vim ~/bin/sys_info_page 

然后输入以下程序:

 #!/bin/bash #        echo "<html>" echo " <head>" echo " <title>Page Title</title>" echo " </head>" echo " <body>" echo " Page body." echo " </body>" echo "</html>" 

我们的第一个版本包含一个shebang行,一个注释(欢迎)和一系列echo命令,每行输出一个。 保存文件后,使其可执行并尝试运行:

 [me@linuxbox ~]$ chmod 755 ~/bin/sys_info_page [me@linuxbox ~]$ sys_info_page 

启动后,HTML文档的文本应出现在屏幕上,因为脚本中的echo命令将其行发送到标准输出。 再次运行程序,并将程序的输出重定向到sys_info_page.html文件,然后在Web浏览器中查看结果:

 [me@linuxbox ~]$ sys_info_page > sys_info_page.html [me@linuxbox ~]$ firefox sys_info_page.html 

到目前为止,一切都很好。

在开发程序时,您应该始终牢记简单性和清晰度。 当程序易于阅读和理解时,维护会更容易,更不用说在可以减少手动输入量的情况下程序更易于编写的事实。 该程序的当前版本运行良好,但可以简化。 将所有echo命令组合为一个绝对可以使将来在程序输出中添加新行变得更加容易。 因此,我们如下更改程序:

 #!/bin/bash #        echo "<html> <head> <title>Page Title</title> </head> <body> Page body. </body> </HTML>" 

带引号的字符串可以包含换行符,因此可以包含多行文本。 外壳将继续读取文本,直到遇到右引号为止。 此规则也适用于命令行:

 [me@linuxbox ~]$ echo "<html> > <head> > <title>Page Title</title> > </head> > <body> > Page body. > </body> > </html>" 

每行开头的>符号提示输入由PS2变量定义的外壳。 只要输入多行指令,它就会出现。 该功能仍然不清楚,但是,当我们熟悉多行程序指令时,其优势将变得显而易见。

第二步:添加一些数据


现在,该程序可以生成最小的文档,将一些数据添加到报告中。 为此,请进行以下更改:

 #!/bin/bash #        echo "<html> <head> <title>System Information Report</title> </head> <body> <h1>System Information Report</h1> </body> </html>" 

在报告正文中添加了页面名称和标题。

变量和常量


我们的脚本中有问题。 您是否注意到系统信息报告行重复了两次? 通常,对于这样一个很小的场景,这并不是什么大问题,但是可以想象一个非常长的场景,其中该行重复了很多次。 如果在这种情况下需要更改名称,则必须在许多地方进行更改,这是很多手动工作。 是否可以更改脚本,以便仅在其中定义一次字符串? 这将大大简化将来的脚本维护。 是的,这是可能的,例如,如下所示:

 #!/bin/bash #        title="System Information Report" echo "<html> <head> <title>$title</title> </head> <body> <h1>$title</h1> </body> </html>" 

通过创建一个名为title的变量并为其分配值System Information Report,我们利用了参数替换的优势并将字符串放置在许多位置。

但是如何创建变量? 简单-只需使用它。 当外壳程序遇到变量时,它将自动创建它。 这与许多编程语言不同,在编程语言中,必须在使用变量之前显式声明或定义变量。 在这方面,命令外壳过于宽松,最终会导致一些问题。 例如,考虑在命令行上执行以下脚本:

 [me@linuxbox ~]$ foo="yes" [me@linuxbox ~]$ echo $foo yes [me@linuxbox ~]$ echo $fool [me@linuxbox ~]$ 

我们首先将变量yes赋给变量foo,然后使用echo命令输出其值。 接下来,我们再次尝试显示变量的值,但是通过指定名称fool进行了输入错误,并且得到了一个空字符串。 外壳程序在遇到傻瓜变量后成功创建了傻瓜变量并将其分配为空的默认值,从而解释了此结果。 从此示例可以看出,您需要仔细监视拼写! 了解此示例中实际发生的事情也很重要。 从以前对替代机制的了解,我们知道团队

 [me@linuxbox ~]$ echo $foo 

暴露于参数替换的机制,因此采用以下形式:

 [me@linuxbox ~]$ echo yes 

另一方面,团队

 [me@linuxbox ~]$ echo $fool 

变成

 [me@linuxbox ~]$ echo 

没有什么可以代替空变量! 这可能会导致需要参数的命令出错。 例如:

 [me@linuxbox ~]$ foo=foo.txt [me@linuxbox ~]$ foo1=foo1.txt [me@linuxbox ~]$ cp $foo $fool cp:  'foo.txt'  ,      "cp --help"    . 

我们为两个变量foo和foo1赋值。 然后他们尝试执行cp命令,但他们在第二个参数的名称中输入了错误。 在由查找引擎进行处理之后,cp命令仅收到一个参数,尽管它需要两个参数。

以下是命名变量的一些规则:

  • 变量名称可以由字母数字字符(字母和数字)和下划线组成。
  • 变量名中的第一个字符只能是字母或下划线。
  • 变量名中不允许存在空格和标点符号。

名称变量表示可以更改的值,并且在许多应用程序中,变量都是以这种方式使用的。 但是,我们的应用程序中的title变量用作常量 。 常量(如变量)具有名称并包含值。 唯一的区别是常数的值不改变。 在执行几何计算的应用程序中,您可以定义一个值为3.1415的PI常数,而不是在整个程序中都使用该数字。 外壳不区分常量和变量。 这些术语主要是为了方便程序员使用。 典型的约定是使用大写字母表示常量,使用小写字母表示真实变量。 让我们更改方案以使其符合以下约定:

 #!/bin/bash #        TITLE="System Information Report For $HOSTNAME" echo "<html> <head> <title>$TITLE</title> </head> <body> <h1>$TITLE</h1> </body> </html>" 

在此过程中,我们通过在末尾添加HOSTNAME shell变量的值来补充名称。 这是机器的网络名称。

注意


实际上,外壳程序具有一种保证常量不变性的机制,该机制采用带有-r参数(只读-只读)的内置声明命令的形式。 如果将值分配给TITLE变量,如下所示:

 declare -r TITLE="Page Title" 

Shell不允许将值重新分配给TITLE变量。 这种机制在实践中很少使用,但是它可用并且可以在特别严格的情况下使用。

为变量和常量赋值


我们到了当下,我们对替代机制运作特征的认识开始硕果累累。 如我们所见,将值分配给变量是这样完成的:

 = 

其中变量变量的名称, 是字符串。 与某些其他编程语言不同,shell不关心分配给变量的值的类型。 她将所有值解释为字符串。 通过使用带-i选项的clarify命令,可以强制外壳程序将分配值的范围限制为整数,但实际上,与声明只读变量一样,该功能很少使用。

请注意,在赋值运算符中,变量名称,等号和值之间没有空格。 含义包括什么? 您可以将任何内容扩展为字符串。

 a=z #   a  "z". b="a string" #      . c="a string and $b" #     , # ,   . d=$(ls -l foo.txt) #   . e=$((5 * 7)) #    . f="\t\ta string\n" #  ,   #     . 

在一行中,您可以一次分配多个变量:

 a=5 b="a string" 

使用替换时,变量名称可以括在可选的花括号{}中。 当变量名称在周围的上下文中变得不明确时,这很有用。 以下示例尝试使用变量将myfile重命名为myfile1

 [me@linuxbox ~]$ filename="myfile" [me@linuxbox ~]$ touch $filename [me@linuxbox ~]$ mv $filename $filename1 mv:  'myfile'  ,      "mv --help"    . 

此尝试未成功,因为外壳程序将mv命令的第二个参数解释为新(且为空)变量的名称。 下面显示了如何解决此问题:

 [me@linuxbox ~]$ mv $filename ${filename}1 

通过添加花括号,我们确保外壳程序不会将最后一个字符1解释为变量名的一部分。

注意事项


执行替换时,建议将变量名和命令括在双引号中,以防止外壳程序将行分成单词。 当变量可能包含文件名时,使用引号尤其重要。
我们将利用此机会向报告中添加其他数据,即报告的日期和时间,以及创建报告的用户的名称:

 #!/bin/bash #        TITLE="System Information Report For $HOSTNAME" CURRENT_TIME=$(date +"%x %r %Z") TIME_STAMP="Generated $CURRENT_TIME, by $USER" echo "<html> <head> <title>$TITLE</title> </head> <body> <h1>$TITLE</h1> <p>$TIME_STAMP</p> </body> </html>" 

嵌入式文件


我们研究了两种不同的文本输出方法,它们都使用echo命令。 但是,还有另一种第三种方法,称为内联文档 (在此为文档)或内联脚本 (在此为脚本)。 嵌入式文档是I / O重定向的另一种形式,它将脚本中嵌入的文本传递到标准命令输入。 此重定向的工作方式如下:

  <<    

其中, 命令是通过标准输入接收指定文本的命令的名称, 指示符是标记嵌入式文本结尾的行。 我们将使用其中的嵌入式文档来修改方案:

 #!/bin/bash #        TITLE="System Information Report For $HOSTNAME" CURRENT_TIME=$(date +"%x %r %Z") TIME_STAMP="Generated $CURRENT_TIME, by $USER" cat << _EOF_ <html> <head> <title>$TITLE</title> </head> <body> <h1>$TITLE</h1> <p>$TIME_STAMP</p> </body> </html> _EOF_ 

该脚本现在使用cat命令和嵌入式文档代替了echo命令。 选择了_EOF_行作为指示符角色(意味着文件 结尾 -文件 结尾 ,共同协议),它标记了嵌入文本的结尾。 请注意,指示符行应放在单独的一行中,并且在其后不能有空格。

但是在这里使用嵌入式文档有什么好处? 几乎没有,只是嵌入式文档中的引号对shell失去了特殊的含义。 以下是在命令行上使用嵌入式文档的示例:

 [me@linuxbox ~]$ foo="some text" [me@linuxbox ~]$ cat << _EOF_ > $foo > "$foo" > '$foo' > \$foo > _EOF_ some text "some text" 'some text' $foo 

如您所见,命令外壳程序不注意引号。 她将它们解释为普通字符。 因此,我们可以将引号自由地插入到嵌入式文档中。 在开发报告程序时可以使用这种情况。

嵌入式文档可以与任何接受来自标准输入的数据的命令一起使用。 以下示例使用内置文档向ftp程序发送命令序列,以从远程FTP服务器下载文件:

 #!/bin/bash #     FTP FTP_SERVER=ftp.nl.debian.org FTP_PATH=/debian/dists/stretch/main/installer-amd64/current/images/cdrom REMOTE_FILE=debian-cd_info.tar.gz ftp -n << _EOF_ open $FTP_SERVER user anonymous me@linuxbox cd $FTP_PATH hash get $REMOTE_FILE bye _EOF_ ls -l $REMOTE_FILE 

如果将重定向运算符<< <<替换为<<-,命令外壳将忽略嵌入式文档中的初始制表符。 因此,可以将缩进添加到嵌入式文档中以提高可读性:

 #!/bin/bash #     FTP FTP_SERVER=ftp.nl.debian.org FTP_PATH=/debian/dists/stretch/main/installer-amd64/current/images/cdrom REMOTE_FILE=debian-cd_info.tar.gz ftp -n <<- _EOF_ open $FTP_SERVER user anonymous me@linuxbox cd $FTP_PATH hash get $REMOTE_FILE bye _EOF_ ls -l $REMOTE_FILE 

但是,使用此功能并不总是很方便,因为对于缩进而言,许多文本编辑器(和程序员本身)更喜欢使用空格字符而不是制表符。

结论


在本章中,我们开始开发一个项目,在该项目中我们将经历创建脚本的所有阶段。 我们熟悉变量和常量及其使用的功能。 它们比用于替代的其他软件组件更多。 我们还看到了如何在脚本中组织信息的输出,并熟悉了嵌入文本块的不同方法。

关于作者


William Shotts是一位拥有30多年经验的专业软件开发人员,他积极使用Linux操作系统已有20多年了。 他在软件开发,技术支持,质量控制和编写文档方面拥有丰富的经验。 他还是LinuxCommand.org的创建者,LinuxCommand.org是专门针对Linux的教育和教育网站,其中使用Linux命令行提供新闻,评论和支持。

关于科学编辑


JordiGutiérrezHermoso是一位计算机程序员,数学家和道德黑客。 自2002年以来,它不仅在家庭中而且在工作中仅使用Debian GNU / Linux。 Jordi参与了GNU Octave的开发,GNU Octave是一种与Matlab以及分布式版本控制系统Mercurial很大程度上兼容的免费计算环境。 他喜欢纯数学和应用数学,滑冰,游泳和编织。 最近,他对温室气体排放问题进行了很多思考,并参与了拯救犀牛的行动。

»这本书的更多信息可以在出版商的网站上找到
» 目录
» 摘录

小贩优惠券可享受25%的折扣-Linux

支付纸质版本的书后,就会通过电子邮件发送电子书。

Source: https://habr.com/ru/post/zh-CN465899/


All Articles