在执行“ps aux | grep 进程”时删除带“grep”的那行

通常情况下,我们总是会结合使用psgrep的方式来筛选出只包含某个进程名的那些行,比如:

$ ps aux | grep nginx
root      9926  0.0  0.1  23388   948 ?        Ss   Mar15   0:00 nginx: master process ./sbin/nginx
nobody   21964  0.0  0.3  23388  1536 ?        S    Mar16   0:16 nginx: worker process
nobody   21965  0.0  0.4  23388  2032 ?        S    Mar16   0:14 nginx: worker process
nobody   21966  0.0  0.4  23716  2192 ?        S    Mar16   0:16 nginx: worker process
root     29249  0.0  0.1  11744   920 pts/0    S+   23:15   0:00 grep --color=auto nginx

结果是出来了,但你有没有注意到最后多出了一行?那是什么?那其实就是我们的 grep 命令本身的命令行。 因为它的命令行中也包含了被筛选的内容(nginx),所以自然也会被包含进来。

所以怎么去掉?先说答案,像下面这样即可:

$ ps aux | grep '[n]ginx'
root      9926  0.0  0.1  23388   948 ?        Ss   Mar15   0:00 nginx: master process ./sbin/nginx
nobody   21964  0.0  0.3  23388  1536 ?        S    Mar16   0:16 nginx: worker process
nobody   21965  0.0  0.4  23388  2032 ?        S    Mar16   0:14 nginx: worker process
nobody   21966  0.0  0.4  23716  2192 ?        S    Mar16   0:16 nginx: worker process

解释

grep(全局正则表达式打印,Global Regular Expression Print),是一种正则表达式模式匹配工具:在输入中搜索/匹配内容,并打印出匹配的内容。 也就是说在搜索匹配时执行的是模式匹配,而不是简单地单个字符的依次比较匹配

在上面的用例中,[n]这个模式在正则表达式中的含义是:中括号中的字符n必须出现一次。那么grep '[n]ginx'的含义是:在输入中搜索匹配nginx这个字符串。 因此就含义本身而言,grep '[n]ginx'整体的含义等价于grep nginx。也即:如果输入相同,它们匹配到的内容完全相同。

那么,前面的例子怎么解释?很好解释:两个命令的输入并不相同。尽管它们的输入都是来自ps aux,但是grep这个命令本身的命令行在被ps枚举出来时是不一样的。

  • 对于ps aux | grep nginx,grep 命令的命令行是:grep nginx
  • 对于ps aux | grep '[n]ginx',grep 命令的命令行是:grep [n]ginx

由于grep nginxgrep '[n]ginx'都是在输入中搜索匹配nginx,但是因为上述后者的grep命令行为grep [n]ginx。因此不被包含在结果中。这,就是原因。

为什么要加单引号?

像上面这样的比较简单的字符串的匹配,不加引号基本上不会出错。

但是,在 bash 这种完全基于字符串的语言中,任何人都能轻易写出漏洞百出的脚本代码

比如就本文的例子而言:[]不仅是正则表达式中的特殊字符,它还是bash的路径名展开(pathname expansion)语法的一部分:bash这个shell在执行我们的命令前会分析我们输入的命令, 并且执行若干个展开步骤中的路径名展开(pathname expansion),最后才是执行命令。

那么何为路径名展开?你可以简单地理解为替换通配符,就像我们可以用*代替当前目录下的所有文件一样。

展开有成功也有失败:

  • 若成功:展开前的特殊字符被路径名替换;
  • 若失败:默认保持不变;

举个例子:

  • 如果当前目录下没有一个名为nginx的文件,grep [n]ginx(注意没有引号)会展开成grep [n]ginx,没变。
  • 如果当前目录下一个名为nginx的文件,grep [n]ginx(注意没有引号)会展开成grep nginx,中括号没了。

所以,后者得不到期望的结果。

为什么加单引号?单引号可以避免 bash 做路径名展开

单引号会作为参数的一部分传递给grep吗?不会,bash 还会执行一个叫Quote Removal的步骤,将(不是用户特意产出的)引号给移除掉。

参考链接:

发表于:2015年04月09日 ,阅读量:2335 ,标签:linux · GREP

版权声明:若非特别注明,本站所有文章均为作者原创,转载请务必注明原文地址。