问题描述
我最近看到了这个one-liner:
$ ps -ef | grep [f]irefox
thorsen 16730 1 1 Jun19 ? 00:27:27 /usr/lib/firefox/firefox ...
所以它似乎在数据中返回了”firefox”的进程列表,但是遗漏了grep进程本身,因此看起来大致相当于:
ps -ef |grep -v grep| grep firefox
我无法理解它是如何工作的。我查看了grep和其他地方的手册页,但没有找到解释。
如果我跑:
$ ps -ef | grep firefox > data
$ grep [f]irefox data
thorsen 15820 28618 0 07:28 pts/1 00:00:00 grep --color=auto firefox
thorsen 16730 1 1 Jun19 ? 00:27:45 /usr/lib/firefox/firefox ....
[t]瑞克似乎停止了工作!
这里有人会知道我发生了什么事。
谢谢。
最佳解决思路
方括号表达式是bash shell(以及其他shell)的一部分,grep的字符类模式匹配。
默认情况下,grep
程序了解POSIX基本正则表达式。有了它,您可以定义字符类。例如,ps -ef | grep [ab9]irefox
可以找到”airefox”,”birefox”,”9irefox”(如果存在的话),但不能找到”abirefox”。
命令grep [a-zA-Z0-9]irefox
甚至可以找到所有以一个字母或数字开头且以”irefox”结尾的进程。
因此ps -ef | grep firefox
会在其中搜索带有firefox
的行。由于grep进程本身有”firefox”,grep也会找到它。通过添加[]
,我们只搜索字符类”[f]”(仅包含字母”f”,因此只相当于没有括号的”f”)。现在括号的优点是字符串”firefox”不再出现在grep命令中。因此,grep本身不会出现在grep结果中。
因为通常没有很多人熟悉方括号作为字符类匹配和正则表达式,所以第二个结果可能看起来有点神秘。
如果要修复第二个结果,可以这样使用它们:
ps -ef | grep [f]irefox > data
grep firefox data
次佳解决思路
原因是字符串
grep firefox
匹配模式firefox
,但字符串
grep [f]irefox
与模式[f]irefox
(相当于模式firefox
)不匹配。
这就是为什么第一个grep匹配它自己的进程命令行,而第二个grep没有。