lin*_*fex 10 command-line bash grep
我正在学习 bash 代码,今天我正在学习命令grep。
如果我跑
$ ps -fU user | grep thunderbird
终端显示:
user 17410 1 0 10:09 ? 00:00:20 /usr/lib/thunderbird/thunderbird
user 18990 15896 0 12:25 pts/1 00:00:00 grep --color=auto thunderbird
Run Code Online (Sandbox Code Playgroud)
但如果我跑:
$ ps -fU user | grep [t]hunderbird
Run Code Online (Sandbox Code Playgroud)
终端显示:
user 17410 1 0 10:09 ? 00:00:20 /usr/lib/thunderbird/thunderbird
Run Code Online (Sandbox Code Playgroud)
为什么?我阅读了指南,但我不明白。
ter*_*don 14
这里有两个问题。首先,当您运行 时ps | grep ...,该grep过程也会显示在 的输出中ps。默认ps输出包括启动进程的参数,而不仅仅是进程的名称。这意味着如果您运行grep foo,并且有一个正在运行的进程被调用foo,那么将有两个ps结果匹配foo:foo进程和它grep本身,因为它正在搜索foo. 这就是为什么你在运行时会得到两行ps -f | grep thunderbird。
现在,这[ ]是一个正则表达式构造,它定义了一个字符列表,一个字符类。例如,[abc]将匹配a或b或c。当您运行ps -f | grep [t]hunderbird时,该类只包含一个字符,因此相当于thunderbird没有括号。然而,这次grep进程是[t]hunderbird作为参数启动的,而不是thunderbird。因此,其输出中的ps行将包含[t]hunderbird. 它看起来像这样:
terdon 23101 10991 0 16:53 pts/3 00:00:00 grep --color [t]hunderbird
Run Code Online (Sandbox Code Playgroud)
这意味着它在您运行时不匹配,ps -f | grep thunderbird因为它包含[t]hunderbird而不是thunderbird.
这是避免grep在运行时匹配进程本身的常见技巧ps | grep。另一种选择是运行ps -f | grep foo | grep -v grep以排除grep. 然而,最好的方法是使用专门为此设计的程序pgrep:
$ pgrep -l thunderbird
11330 thunderbird
Run Code Online (Sandbox Code Playgroud)
小智 6
在第一种情况下,您要查找任何带有“thunderbird in”一词的进程。有两个thunderbird 和grep 命令本身。
在第二个中,您还在寻找t后跟 的字符hunderbird,因为 [t] 表示匹配方括号中列出的任何字符,其中只有一个,即字母 t,但这次您的两个进程是
user 17410 1 0 10:09 ? 00:00:20 /usr/lib/thunderbird/thunderbird
user 18990 15896 0 12:25 pts/1 00:00:00 grep --color=auto [t]hunderbird
Run Code Online (Sandbox Code Playgroud)
第二个过程不匹配,因为 rexep [t]hunderbird 与文字字符串 不匹配,[t]hunderbird因为 ] 阻止了匹配。