9.11 在其他命令的输出中搜索特定内容

$ ls -1 | grep 1960

grep命令单独使用时就很强大,但把它作为其他程序输出的过滤器来使用,才真正显示出它的光彩。例如,假设你把所有John Coltrane的MP3按专辑(是的,总共66个,Coltrane相当优秀)组织到单独的子文件夹中,每个文件夹的名称以年份作为开始。部分列表如下所示(ls命令使用了-1选项,所以每行只显示一个结果):

  1. $ ls -1
  2. 1956_Coltrane_For_Lovers
  3. 1957_Blue_Train
  4. 1957_Coltrane_[Prestige]
  5. 1957_Lush_Life
  6. 1957_Thelonious_Monk_With_John_Coltrane

现在,如果你只想看看自己所有的Coltrane在1960年发行的专辑,该怎么办呢?将ls -1的结果通过管道输出到grep,几秒钟内就能得到答案。如下所示:

  1. $ ls -1 | grep 1960
  2. 1960_Coltrane_Plays_The_Blues
  3. 1960_Coltrane's_Sound
  4. 1960_Giant_Steps
  5. 1960_My_Favorite_Things

在经过思考以后,你会发现按这种方式来使用grep,其用法至少也有几百种。这里再演示另一种功能强大的用法。ps命令可以列出运行中的进程,而-f选项能够让ps提供完整的列表,其中包括每个进程的很多信息;而-U选项,后面跟上用户名称,可以限制只输出那个用户拥有的进程。通常,ps -fU scott会产生一个很长的列表,如果要搜索特定进程的信息,这种输出就太长了。不过,在grep的帮助下,就能够轻松地限制输出内容。

说明 为了节省篇幅,这里删除了一些使用ps命令通常可以看到的信息。

  1. $ ps -fU scott | grep firefox
  2. scott 17623 /bin/sh /opt/firefox/firefox
  3. scott 17634 /opt/firefox/firefox-bin
  4. scott 1601 grep firefox

ps命令会列出用户scott拥有的全部进程(实际上有64个),但将输出通过管道发给grep命令之后,只列出其中包含firefox的那些进程。遗憾的是,输出的最后一行是错误的。你关心的只是实际的Firefox程序,而不是用grep搜索firefox这样的信息。要在grep结果中隐藏firefox的搜索信息,试试以下命令:

  1. $ ps -fU scott | grep [f]irefox
  2. scott 17623 /bin/sh /opt/firefox/firefox
  3. scott 17634 /opt/firefox/firefox-bin

现在,grep的搜索内容是通过正则表达式的一个范围(从f到f)来定义的,用它可以找到ps输出中包含firefox的那些行(表示相应的进程正在运行Firefox)。不过,它不匹配grep行,因为这行的内容实际上是[f]irefox,所以不匹配。这里grep命令也不能匹配原始的命令字符串ps -ef | grep [f]irefox,因为它包含了[]字符,而用于搜索[f]irefoxgrep在运行时搜索的是精确的“firefox”这个词。这点难理解了吧,不过,亲自试一试,多仔细想想,就能领悟其意义了。