欢迎来到初学者级别的 Bash Shell 脚本的第 2 部分。 本文将深入探讨一些更独特的方面 bash 脚本。 它将继续使用熟悉的命令,解释任何新内容,并涵盖标准输出、标准输入、标准错误、“管道”和数据重定向。
添加评论#
随着您的脚本变得更加复杂和实用,您将需要添加注释以记住您在做什么。 如果您与其他人分享您的脚本,评论将帮助他们理解思考过程以及您打算让您的脚本做什么。 从上一篇文章中回忆起有数学方程。 新版本中添加了一些注释。 请注意,在 learnToScript.sh 文件(如下所示)中,注释是前面带有井号的行。 当脚本运行时,这些行不会出现。
#!/bin/bash #Let's pick up from our last article. We #learned how to use mathematical equations #in bash scripting. echo $((5+3)) echo $((5-3)) echo $((5*3)) echo $((5/3))
[zexcon ~]$ ./learnToScript.sh 8 2 15 1
管道操作员 |
我们将使用另一个名为 grep 的工具来介绍管道运算符。
Grep 在一个或多个输入文件中搜索包含与指定模式匹配的行。 默认情况下,Grep 会输出匹配的行。
https://www.gnu.org/software/grep/
Paul W. Frields 在 Fedora 杂志提供了关于 grep 的良好背景。
命令行快速提示:使用 grep 进行搜索
您会在上方找到管道键 Enter 钥匙。 Enter 通过按 Shift + 。 (英文键盘)
既然你们都熟悉了 grep,请看一个 example 管道命令的使用。 在命令行输入 ls -l | grep 学习
[zexcon ~]$ ls -l | grep learn
-rwxrw-rw-. 1 zexcon zexcon 70 Sep 17 10:10 learnToScript.sh
通常 ls -l 命令会在您的屏幕上提供文件列表。 这里 ls -l 命令的完整结果通过管道传送到搜索字符串 learn 的 grep 命令中。 将管道命令想象成一个过滤器。 运行命令,在本例中为 ls -l,结果仅限于目录中的文件。 这些结果通过管道命令发送到 grep 搜索工作学习并且只出现该行。
再看一张 example 试着把这个家钉牢。 less 命令将允许您查看超出一个屏幕尺寸的命令的结果。 以下是 less 命令的手册页中的简要说明。
Less 是一个类似于 more(1) 的程序,但它允许在文件中向后移动以及
向前移动。 此外,less 在开始之前不必读取整个输入文件,所以
对于大型输入文件,它比 vi(1) 等文本编辑器启动得更快。 较少使用 termcap(或
terminfo 在某些系统上),因此它可以在各种终端上运行。 甚至还有有限的支持
硬拷贝终端的端口。 (在硬拷贝终端上,应在顶部打印的行
屏幕的前缀带有插入符号。)
Fedora 34 手册(手册)页
那么让我们看看使用 pipe 和 less 命令会是什么样子
[zexcon ~]$ ls -l /etc | less
total 1504 drwxr-xr-x. 1 root root 126 Jul 7 17:46 abrt -rw-r--r--. 1 root root 18 Jul 7 16:04 adjtime -rw-r--r--. 1 root root 1529 Jun 23 2020 aliases drwxr-xr-x. 1 root root 70 Jul 7 17:47 alsa drwxr-xr-x. 1 root root 14 Apr 23 05:58 cron.d drwxr-xr-x. 1 root root 0 Jan 25 2021 cron.daily : :
为了便于阅读,此处已对结果进行了修剪。 使用键盘上的箭头键向上或向下滚动。 与命令行不同,如果结果滚动到屏幕外,您可能会错过结果的顶部,您可以控制显示。 要退出较少的屏幕,请点击 q 键。
标准输出 (stdout)、>、>>、1> 和 1>>
> 或 >> 之前的命令的输出被发送到其名称后面的文件。 请记住 > 和 1> 具有相同的结果,因为 1 代表标准输出(标准输出)。 如果没有出现,则假定为标准输出。 >> 和 1>> 会将数据附加到文件的末尾。 在每种情况下(> 或 >>),如果文件不存在,则会创建该文件。
作为一个 example,假设您想查看 ping 命令输出以查看它是否丢弃了数据包。 与其坐下来观看控制台,不如将输出重定向到文件。 您可以稍后再回来查看数据包是否被丢弃。 这是使用 > 进行重定向的测试。
[zexcon ~]$ ls -l ~ > learnToScriptOutput
这将获取您在终端中看到的正常结果(回忆 ~ 是您的主目录)并将其重定向到 learnToScriptOutput 文件。 您是否注意到 learnToScriptOutput 从未创建但现在文件存在? 有点酷。
total 128 drwxr-xr-x. 1 zexcon zexcon 268 Oct 1 16:02 Desktop drwxr-xr-x. 1 zexcon zexcon 80 Sep 16 08:53 Documents drwxr-xr-x. 1 zexcon zexcon 0 Oct 1 15:59 Downloads -rw-rw-r--. 1 zexcon zexcon 685 Oct 4 16:00 learnToScriptAllOutput -rw-rw-r--. 1 zexcon zexcon 23 Oct 4 12:42 learnToScriptInput -rw-rw-r--. 1 zexcon zexcon 0 Oct 4 16:42 learnToScriptOutput -rw-rw-r--. 1 zexcon zexcon 52 Oct 4 16:07 learnToScriptOutputError -rwxrw-rw-. 1 zexcon zexcon 477 Oct 4 15:01 learnToScript.sh drwxr-xr-x. 1 zexcon zexcon 0 Jul 7 16:04 Videos
标准错误 (stderr)、2> 和 2>>
> 或 >> 之前的命令的错误输出被发送到其名称后面的文件。 请记住 2> 和 2>> 具有相同的结果,但 2>> 会将数据附加到文件的末尾。 那么这些的目的是什么? 如果您只想捕获错误怎么办。 那么 2> 或 2>> 可以提供帮助。 2 表示通常会转到 stderr(标准错误)的输出。 现在通过列出一个不存在的文件将其付诸实践。
[zexcon ~]$ ls -l /etc/invalidTest 2> learnToScriptOutputError
这将获取错误结果并将其重定向到 learnToScriptOutputError 文件。
ls: cannot access '/etc/invalidTest': No such file or directory
所有输出 &>、&>> 和 |&
如果您正在考虑,我不想将标准输出(stdout)和标准错误(stderr)都写入不同的文件。 你很幸运。 在 Bash 5 中,将 stdout 和 stderr 重定向到同一个文件的首选方法是使用 &> 或者您可能猜到的 &>> 附加到文件。
[zexcon ~]$ ls -l ~ &>> learnToScriptAllOutput [zexcon ~]$ ls -l /etc/invalidTest &>> learnToScriptAllOutput
运行这些命令后,两者的输出都出现在同一个文件中,而不会识别错误或标准输出。
total 128 drwxr-xr-x. 1 zexcon zexcon 268 Oct 1 16:02 Desktop drwxr-xr-x. 1 zexcon zexcon 80 Sep 16 08:53 Documents drwxr-xr-x. 1 zexcon zexcon 0 Oct 1 15:59 Downloads -rw-rw-r--. 1 zexcon zexcon 685 Oct 4 16:00 learnToScriptAllOutput -rw-rw-r--. 1 zexcon zexcon 23 Oct 4 12:42 learnToScriptInput -rw-rw-r--. 1 zexcon zexcon 0 Oct 4 16:42 learnToScriptOutput -rw-rw-r--. 1 zexcon zexcon 52 Oct 4 16:07 learnToScriptOutputError -rwxrw-rw-. 1 zexcon zexcon 477 Oct 4 15:01 learnToScript.sh drwxr-xr-x. 1 zexcon zexcon 0 Jul 7 16:04 Videos ls: cannot access '/etc/invalidTest': No such file or directory
如果您直接从命令行工作并希望将所有结果通过管道传输到另一个命令,则可以使用 |& 来实现此目的。
[zexcon ~]$ ls -l |& grep learn -rw-rw-r--. 1 zexcon zexcon 1197 Oct 18 09:46 learnToScriptAllOutput -rw-rw-r--. 1 zexcon zexcon 343 Oct 14 10:47 learnToScriptError -rw-rw-r--. 1 zexcon zexcon 0 Oct 14 11:11 learnToScriptOut -rw-rw-r--. 1 zexcon zexcon 348 Oct 14 10:27 learnToScriptOutError -rwxr-x---. 1 zexcon zexcon 328 Oct 18 09:46 learnToScript.sh [zexcon ~]$
标准输入 (stdin)
在第 1 篇和第 2 篇文章中,您已经多次使用标准输入 (stdin),因为您的键盘在每次键入键时都使用标准输入。 为了改变通常的“它是你的键盘”,让我们在脚本中使用 read 命令。 下面脚本中使用的 read 命令执行其听起来的操作,即读取标准输入。
#!/bin/bash #Here we are asking a question to prompt the user for standard input. i.e.keyboard echo 'Please enter your name.' #Here we are reading the standard input and assigning it to the variable name with the read command. read name #We are now going back to standard output, by using echo and printing your name to the command line. echo "With standard input you have told me your name is: $name"
这 example 提示通过标准输出输入,从标准输入(键盘)获得的信息,使用 read 将其存储在名为 name 的变量中,并通过标准输出显示 name 中的值。
[zexcon@fedora ~]$ ./learnToScript.sh Please enter your name. zexcon With standard input you have told me your name is: zexcon [zexcon@fedora ~]$
进入剧本……
现在把学到的东西放在一个脚本中,看看如何使用它。 以下是之前 learnToScript.sh 文件的新版本。 增加了几行。 它使用附加选项将标准输出、标准错误和两者都添加到一个文件中。 它将标准输出写入 learnToScriptStandardOutput,标准错误写入 learnToScriptStandardError,输出和错误都写入 learnToScriptAllOutput
#!/bin/bash #As we know this article is about scripting. So let's #use what we learned in a script. #Let's get some information from the user and add it to our scripts with stanard input and read echo "What is your name? " read name #Here standard output directed to append a file to learnToScirptStandardOutput echo "$name, this will take standard output with append >> and redirect to learnToScriptStandardOutput." 1>> learnToScriptStandardOutput #Here we are taking the standard error and appending it to learnToScriptStandardError but to see this we need to #create an error. eco "Standard error with append >> redirect to learnToScriptStandardError." 2>> learnToScriptStandardError #Here we are going to create an error and a standard output and see they go to the same place. echo "Standard output with append >> redirect to learnToScriptAllOutput." &>> learnToScriptAllOutput eco "Standard error with append >> redirect to learnToScriptAllOutput." &>> learnToScriptAllOutput
这 example 在同一目录中创建三个文件。 命令 echo 故意输入错误以产生错误。 如果检查所有三个文件,您将在 learnToScriptStandardOutput 中看到一条消息,在 learnToScriptStandardError 中看到一条消息,在 learnToScriptAllOutput 中看到两条消息。 还要注意脚本提示输入它写入 learnToScriptStandardOutput 的名称。
结论
在这一点上,应该开始清楚您可以在命令行中执行的任何操作,也可以在脚本中执行。 在编写其他人可能使用的脚本时,文档非常重要。 继续深入研究脚本,标准输出将更有意义,因为您将是生成它们的人。 在脚本中,您可以使用与命令行相同的内容。 下一篇文章将讨论函数、循环和将继续在此基础上构建的东西。