5.4 其它妙招
在本节中,我们介绍其它几个必备的命令行使用妙招。
5.4.1 命令替换
假设我们想要编辑包含 error
的 Python 源代码文件 (*.py
),在此之前,我们首先需要确定哪些 Python 文件具有这些字符串。为此,我们可以使用下面的命令将其找出来:
这里的 -l
选项让 grep
命令将找出的文件名输出到终端,然后我们就可以用文本编辑器 (如 nvim
) 来编辑这些文件:
代替这种需要两步才能完成的操作,我们也可以要求 Shell 在执行 grep
命令后直接将文件名传递给文本编辑器 (如 nvim
):
Shell 对上述命令 ``
(反引号) 中的内容执行命令替换,也就是说,把 grep
命令的输出作为 nvim
命令的参数。我们从而将两步操作得以合并成一步操作来完成。
使用 ``
(反引号) 算是老式的命令替换用法,更新式的用法是 $()
。所以上面的命令也能改写成如下形式:
我们推荐使用 $()
这种新用法,因为在嵌套命令替换时具有更好的可读性。例如:
xiaodong@codeland:~$ nvim $(grep -l failed $(date +'%Y%m%d').log)
xiaodong@codeland:~$ nvim `grep -l failed \`date +'%Y%m%d'\`.log`
在嵌套时,$()
看起来一目了然,而 ``
(反引号) 则需要转义,其可读性较差。
5.4.2 使用变量
虽然 Shell 本身具有内置变量,而且我们在执行程序时还会碰到环境变量,但是我们在此要讲的却是另一种变量,即用户变量。
用户变量是由我们自己所设置的变量,其目的在于临时保存需要多次使用的数据。这样,当我们需要使用数据时就可以通过变量名来引用它了。因为通常变量名比我们要引用的数据要短很多,所以也让我们减少了不必要的重复输入。
让我们看一个例子:
xiaodong@codeland:~$ LOG=/var/log/pacman.log
xiaodong@codeland:~$ head $LOG
xiaodong@codeland:~$ grep -i error $LOG
我们将变量 LOG
的值设置为 /var/log/pacman.log
,接着通过 $LOG
的形式分别在 head
和 grep
命令中引用它。
5.4.3 重复执行命令
当我为演讲主题准备材料时,我想用 figlet
这个工具来制作一些有趣的 ASCII 艺术字。虽然 figlet
提供了很多艺术样式,但是我并没有见过每一种。要想选择最酷的 ASCII 艺术字,所以我必须把每种样式都浏览一遍。于是,我执行了下面的命令:
xiaodong@codeland:~$ figlet -f ascii9 Linux
xiaodong@codeland:~$ figlet -f bigmono9 Linux
xiaodong@codeland:~$ figlet -f emboss Linux
...
可是,figlet
还有很多样式,这样一个一个的查看实在枯燥乏味。Shell 有没有什么重复执行命令的快捷方法呢?回答是肯定的。利用 Shell 提供的 for
循环,我们可以一遍又一遍的重复执行命令。下面让我们来一次性查看 figlet
的所有样式。
xiaodong@codeland:~$ cd /usr/share/figlet
xiaodong@codeland:~$ for font in *.tlf
> do
> echo "Font: $font"
> figlet -f $(basename $font .tlf) Linux
> done
for
和 in
中间的 font
为循环的变量,*.tlf
表示扩展名为 tlf
的所有文件。do
与 done
之间的内容为循环体,针对当前目录下的每个 tlf
文件都会执行这两条命令。
除了上面多行形式的 for ... in
循环结构外,我们也可以使用其单行形式,例如: