Linux 复杂 Bash 单行示例
Bash 一句台词可以减少工作量,快速实现自动化,并将最终的系统控制权交给您。随着时间的推移,你可能会学会写更复杂的单行文字,而你作为经验丰富的专业人士最终写出的一些东西对于初学者来说几乎是无法理解的。也就是说,Bash 命令和开发语言是高度结构化的 - 并且相对容易理解 - 一旦你了解了它的内部和外部。这真的就像精通一门外语一样。
在本教程中您将学习:
如何编写更高级的 Bash 一行命令和脚本
了解如何将各种命令组合成一行脚本
了解使用
&&
和||
时一个命令的退出代码如何影响其他命令了解如何修改命令的输入,然后由下一个命令使用
更高级的 Bash 俏皮话的用法和现实生活中的示例
Linux 复杂 Bash 单行示例
使用的软件要求和约定
示例 1:过程控制
让我们从一个示例开始,了解如何以易于理解的方式终止 Bash 中的某些进程:
$ sleep 3600 &
[1] 1792341
$ ps -ef | grep 'sleep'
roel 1792441 1701839 0 12:59 pts/13 00:00:00 sleep 3600
roel 1792452 1701839 0 12:59 pts/13 00:00:00 grep --color=auto sleep
首先我们设置一个睡眠命令,持续 3600 秒(一小时),然后我们在进程列表中找到该进程。很好,但我们确实有实际的 grep 命令作为进程列表输出中的额外行。让我们对其进行过滤,然后提取进程 ID,而不是完整的进程信息输出:
$ ps -ef | grep 'sleep' | grep -v grep
roel 1792441 1701839 0 12:59 pts/13 00:00:00 sleep 3600
$ ps -ef | grep 'sleep' | grep -v grep | awk '{print $2}'
1792441
在第一个命令中,我们过滤掉了活动的 grep。在第二个命令中,我们更进一步,使用 awk
命令打印第二列 $2
(在 awk
内部)。现在,我们可以更进一步并实际杀死
该进程。假设我们使用信号 9
来执行此操作,该信号对任何 Linux 进程都具有高度破坏性 (SIGKILL
):
$ ps -ef | grep 'sleep' | grep -v grep | awk '{print $2}' | xargs kill -9
[1]+ Killed sleep 3600
我们可以看到我们的进程被正确终止。虽然这是一个更简单的示例,但它涉及 6 个不同的命令:ps
、grep
、grep
和 awk
、xargs
和kill
。您可以看到 Bash 一句台词如何以多种不同的方式、多种不同的复杂性和数据处理能力级别快速构建复杂性。
并且,要了解有关 xargs 的更多信息,请参阅我们的文章 xargs for Beginners with Examples 和 multi threaded xargs with Examples。
示例2:享受成功和失败的乐趣!
$ echo '0' > a && echo '1' > b && echo '2' > c && ls doesnotexist || ls a && ls b && ls c && ls d && ls e
ls: cannot access 'doesnotexist': No such file or directory
a
b
c
ls: cannot access 'd': No such file or directory
多么复杂的线条啊!然而,一旦你知道如何阅读它,或者你已经这样做了,它就会变得非常容易阅读。让我们通过将命令分解为更容易理解和遵循的更小的块来证明这个断言是有效的:
$ echo '0' > a && echo '1' > b && echo '2' > c
这组命令的所有功能与以下命令相同,但有一个小警告:
$ echo '0' > a
$ echo '1' > b
$ echo '2' > c
那么有什么区别(以及小警告)?
在最后一系列命令中,无论前一个命令的结果是什么,每个命令都将被执行。前一个序列(使用 &&
)只会继续到第二个 echo
如果第一个命令的结果是 0
> (即成功 - 在 Bash 中命令的成功由 0
表示,失败则用 1
或更高的退出代码表示)。
因此,使用&&
的命令序列也可以写成如下:
$ echo '0' > a
$ if [ ${?} -eq 0 ]; then echo '1' > b; fi
$ if [ ${?} -eq 0 ]; then echo '2' > c; fi
$ {?}
(或短语法中的 $?
)变量始终包含最后一个命令的结果,即退出代码 (0
、1
或更高)由最后一个命令生成。
正如我们所看到的,单行创建 echo '0' > a && echo '1' > b && echo '2' > c
现在肯定更容易看懂和理解,而且肯定会降低上面显示的相应和匹配代码的复杂性。
接下来我们再执行一个命令:
$ echo '0' > a && echo '1' > b && echo '2' > c && ls doesnotexist
ls: cannot access 'doesnotexist': No such file or directory
现在读起来容易多了,对吧?
我们刚刚添加了另一个命令,即 ls doesnotexist
,前提是该命令之前的命令(在本例中,整个行,因为所有命令都通过链式设置中的 &&
连接起来) ,其中错误的命令将破坏链并完全停止链的执行)已成功。当所有命令成功时,ls
就会被执行,并且会产生一个错误,因为该文件确实不存在 ?
那么如果我们最后加入另一个 &&
会发生什么呢?命令链会像我们所说的那样终止吗?让我们稍微调整一下命令:
$ echo '0' > a && echo '1' > b && echo '2' > c && ls doesnotexist && echo 'surely not'
ls: cannot access 'doesnotexist': No such file or directory
而且,它肯定没有执行。然后让我们从原始示例中介绍链中的下一个命令:
$ echo '0' > a && echo '1' > b && echo '2' > c && ls doesnotexist || ls a
ls: cannot access 'doesnotexist': No such file or directory
a
你能看到发生了什么吗?这里我们有一个新的语法符号,即 ||
,它与 &&
不同,它仅在前一个命令中出现非零结果时才执行。请注意,||
和 &&
仅适用于最后一个命令,而不适用于命令链,即使人们可以将其视为整个命令链。
因此,您可以将 &&
视为英语中的等效 and
,并且在某种程度上,是编程语言中常见的 and
,但有所不同在这里,我们检查 &&
之前的条件,并在退出条件为 0
的情况下执行其后面的内容。
另一个变化是,当使用 &&
语法时,大多数编程语言都会以二进制 1
形式检查真实性。例如考虑伪代码; if test1_flag && test2_flag then...
如果二进制标志,通常会评估为true总体(从而执行
和 then
命令) >test1_flagtest2_flag
为 1 或 true,而在 Bash 中,真实性 由 0
表示(而不是 1
) 从最后一个命令退出状态!
您可以将 ||
视为英语等效的 or
(or
如 或如果失败则执行... )。在这种情况下,与通用编程语言有更紧密的联系:当通用程序语言检查时,例如 if test1_flag || test2_flag then ...
,然后二进制正 test1_flag
(即值 1
)或 test2_flag
将产生整体条件true(因此 then
子句将被执行)。我们在 Bash 中也看到了同样的情况;如果命令的退出代码非零(即 1
或在某些情况下更高的值),则将执行 ||
子句后面的命令。
现在让我们回到原始命令并完整解析它:
$ echo '0' > a && echo '1' > b && echo '2' > c && ls doesnotexist || ls a && ls b && ls c && ls d && ls e
ls: cannot access 'doesnotexist': No such file or directory
a
b
c
ls: cannot access 'd': No such file or directory
你能看到会发生什么吗?因为 ls doesnotexist
命令在内部失败并产生非零输出(在 Bash 中使用 ls doesnotexist; echo $?
进行验证;输出为 2
),or
(||
) 子句被触发,接下来我们执行 ls
。把它想象成一条流向不同方向的链条,但它仍然是一条链条。
当 ls a
命令成功后,后面跟着 and
(&&
) 子句,执行下一个命令,依此类推。请注意,执行到达 ls d
,并显示相同的输出 (ls: 无法访问 'd': No such file or directory
),但 >ls e
命令未执行!这是预期的,因为使用了 &&
并且 ls d
命令失败。因此,ls e
永远不会被执行。
结论
你越熟练地编写 Bash 语句,你的 Bash 语句脚本就会变得越快、越好、越不容易出错、越流畅,并且你花在编写它们上的时间也会越少。 Bash 语言的开发人员已将所有控制权交给您。今天您将使用该控件做什么?
请在下面给我们留言,告诉我们您最酷的单行作品!