您对bash的了解程度如何?


您每天都使用外壳吗? 准备解决一些逻辑问题并学习新知识吗? 欢迎来到猫。

这里介绍的某些任务不会带来真正的好处,因为它们会影响某些复杂的边界情况。 另一部分对于经常使用该shell并阅读其他人的脚本的用户很有用。

注意:在撰写本文时,作者在Windows 10的Linux子系统中使用了bash 4.4.12(1)-release。任务的复杂性不同。

输入/输出流


任务1

$ cat 1 The cake is a lie! Wanted! Cake or alive $ cat 1 | head | tail | sed -e 's/alive/dead/g' | tee | wc -l > 1 

命令后文件1中有几行?

答案
1个

解说
在解释了命令之后,但是在运行所有程序之前,bash与指定的输入/输出流一起工作。 因此,在启动第一个程序之前将文件1清除,并且cat打开已经清除的文件。

任务2

 $ cat file1 I love UNIX! $ cat file2 I don't like UNIX $ cat file1 <file2 

屏幕上将显示什么?

答案
I love UNIX!

解说
指定文件后,某些程序会在stdin上运行。

任务3

 $ cat file Just for fun $ cat file 1>&2 2>/dev/null 

屏幕上将显示什么?

答案
Just for fun

解说
有一个误解,认为序列1>&2将第一个线程重定向到第二个线程,但是事实并非如此。 从任务中考虑团队。 在解释输入的命令开始时,流表如下所示:
01个2
标准输入标准输出标准差

bash检测序列1>&2并将单元2的内容复制到单元1:
01个2
标准输入标准差标准差

在检测到序列2>/dev/null解释器将值写入单元格2,其他单元格则保持不变:
01个2
标准输入标准差/开发/空

bash还显示错误流,以便我们在屏幕上找到文件的文本。

任务4
如何将stdout输出发送到stderr,如何将stderr输出发送到stdout?

答案
4>&1 1>&2 2>&4

解说
该原理与上一个任务完全相同。 这就是为什么我们需要额外的流来临时存储的原因。

可执行文件


任务5

给定文件test.sh

 #!/bin/bash ls $* ls $@ ls "$*" ls "$@" 

执行以下命令:

 $ ls 1 2 3 test.sh $ ./test.sh 1 2 3 

脚本将输出什么?

答案
1 2 3
1 2 3
ls: cannot access '1 2 3': No such file or directory
1 2 3


解说
没有引号,变量$ *和$ @相同,并被扩展为脚本的所有给定位置参数,并用空格分隔。 在引号中,公开方法更改:$ *变为“ $ 1 $ 2 $ 3”,而$ @依次变为“ $ 1”“ $ 2”“ $ 3”。 由于文件“ 1 2 3”不在目录中,因此ls显示错误

任务6

在当前目录中,创建一个权限为755且具有以下内容的-c文件:

 #!/bin/bash echo $1 

将$ PATH变量清零,然后尝试执行:

 $ PATH= $ -c "echo SURPRISE" 

屏幕上将显示什么? 如果您重新输入最后一条命令会怎样?

答案
第一次将显示SURPRISE ,第二次将显示echo SURPRISE

解说
如果PATH为空,则Shell将开始在当前目录中搜索文件。 -c刚刚位于。 由于可执行文件是文本文件,因此以shebang为主题读取第一行。 团队根据模板组装:

 <shebang> <filename> <args> 

因此,在执行之前,我们的命令如下所示:

 /bin/bash -c "echo SURPRISE" 

结果,这完全不是我们想要做的。

如果您第二次执行它,那么外壳程序将从缓存中获取有关-c的信息并正确执行它。 保护自己免受这种意外影响的唯一方法是在shebang上增加两个负号。

变数


任务7

 $ ls file $ cat <$(ls) $ cat <(ls) 

第一种和第二种情况将显示什么?

答案
第一个将显示文件文件的内容,第二个将显示文件名。

解说
在第一种情况下,执行替换

 cat <file 

在第二种情况下, <(ls)将由一个命名管道替换,该命名管道由输入连接到stdout ls和来自stdin cat的输出连接。

替换后,命令将采用以下形式:

 cat /dev/fd/xx 


任务8

 $ TEST=123456 $ echo ${TEST%56} 

屏幕上将显示什么?

答案
1234

解说
有了这样的记录,模式匹配(#-从变量的开头; ##-从变量的开头贪婪;%-从变量的结尾贪婪; %%-从变量的结尾贪婪地),并且在替换时将其删除。 变量的内容保持不变。 因此,例如,方便地获取不带扩展名的文件名。

 $ TEST=file.ext $ echo ${TEST%.ext} file 


任务9

 $ echo ${friendship:-magic} 

屏幕上将显示什么?

答案
如果定义了友谊变量,则变量的内容。 否则,魔术。

解说
在文档中,此魔术称为“未设置或为空”,并且允许您在一行中使用变量的指定默认值。

执行顺序


任务10

 while true; false; do echo Success done 

屏幕上将显示什么?

答案
没事

解说
while和if语句允许您将整个动作序列塞入条件中,但是仅在最后一条命令中才考虑结果(返回码)。 由于它为假,因此循环甚至不会开始。

任务11

 $ false && true || true && false && echo 1 || echo 2 

屏幕上将显示什么?

答案
2

解说
考虑到只考虑了最后一条命令的返回码,请添加括号以使命令明确并简化命令:

 ((((false && true) || true) && false) && echo 1) || echo 2 (((false || true) && false) && echo 1) || echo 2 ((true && false) && echo 1) || echo 2 (false && echo 1) || echo 2 false || echo 2 echo 2 


评论,建议和其他任务在评论或PM中受到欢迎。

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


All Articles