我正在学习 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
但如果我运行:
$ ps -fU user | grep [t]hunderbird
终端显示:
user 17410 1 0 10:09 ? 00:00:20 /usr/lib/thunderbird/thunderbird
为什么?我读了指南,但我不明白。
答案1
这里有两个问题。首先,当你运行 时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
这意味着运行时它不匹配,ps -f | grep thunderbird
因为它包含[t]hunderbird
和不包含thunderbird
。
grep
这是在运行 时避免匹配进程本身的常用技巧ps | grep
。另一种选择是运行ps -f | grep foo | grep -v grep
以排除grep
。然而,最好的方法是使用专门为此设计的程序pgrep
:
$ pgrep -l thunderbird
11330 thunderbird
答案2
在第一种情况下,您要查找带有单词 thunderbird 的任何进程。有两个 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
第二个进程不匹配,因为 rexep [t]hunderbird 与文字字符串 [t]hunderbird
因为] 阻止了匹配。
答案3
首先,是否grep --color=auto thunderbird
会出现在进程表中,从而出现在的输出中ps
取决于时间,即您的系统有多忙,以及需要多长时间才能ps
在其输出中显示已并发启动的内容(通过解析进程表),grep
在本例中。虽然这种情况极不可能发生,但我们可以假设它将grep
出现在的输出中ps
。
现在,[]
是一个 grep 语法,这意味着(如果没有其他标记)匹配 内的任何字符[]
。因此,当您使用 时grep '[t]hunderbird'
,grep
会将 视为[t]
仅匹配t
,因此它不会出现在输出中。
在使用时grep thunderbird
,如果它在进程表中存在,我们会grep
在输出中找到该进程,因为我们grep
对同一件事进行 -ping ,即grep thunderbird
。
还请注意,这grep
是一个别名,会grep --color=auto
导致它也出现在输出中。
答案4
中的 []grep
用于字符匹配。如果我们取
grep [tb]all my_file.txt
它相当于
grep tall my_file.txt
grep ball my_file.txt
它将grep
通过取 t+all 来执行,然后它将grep
通过取 b+all 来执行。
例如:如果我们想在文件中查找单词 ABC 或 BBC,我们可以使用以下 grep 命令:
grep [AB]BC file_name
这里 [] 将grep
通过采用 A 来扩展单词,然后它将通过使用 B 来扩展单词,从而创建 ABC 和 BBC。