如何防止“grep”出现在 ps 结果中?

Way*_*ner 365 grep ps

当我搜索一些不存在的进程时,例如

$ ps aux | grep fnord                          
wayne    15745  0.0  0.0  13580   928 pts/6    S+   03:58   0:00 grep fnord
Run Code Online (Sandbox Code Playgroud)

显然我不关心 grep - 这和搜索ps过程一样有意义!

如何防止 grep 出现在结果中?

Way*_*ner 531

原来在keychain 中找到了一个解决方案。

$ ps aux | grep "[f]nord"
Run Code Online (Sandbox Code Playgroud)

通过在字母周围加上括号并在字符串周围加上引号,您可以搜索正则表达式,即“找到字符 'f' 后跟 'nord'”。

但是由于您将括号放在模式 'f' 中,现在后面是 ']',所以grep不会显示在结果列表中。尼托!

  • @acolyte: ps 的输出将包括以 `grep [f]nord` 结尾的行。但是,该行不会通过 grep 过滤器,因为字符串 `[f]nord` 与正则表达式 `[f]nord` 不匹配。 (32认同)
  • Grepping `ps` 的输出可能是一个老技巧,但它不可靠。[使用`pgrep`](http://unix.stackexchange.com/questions/74185/how-can-i-prevent-grep-from-showing-up-in-ps-results/74190#74190)(如果可用)。 (27认同)
  • @LarsH 有趣,谢谢!我会建议`ps aux | grep fnord | grep -v grep` ...这似乎已经被一些人建议了...大声笑 (9认同)
  • @naxa 想象一下,您有一个名为“fnord”的程序和一个名为“safnorde”的程序。或者有一个名为“bfnord”的用户,你最终杀死了他的所有进程。等等。 (9认同)
  • @progo 是的,即使在 bash 中,您也确实需要引用 `[`。尝试使用当前目录中名为“fnord”的文件。 (6认同)
  • 如果您使用`bash`,则不需要转义或引用`[]`。在 `zsh` 中,你只需要转义第一个:`\[c]onky == "[c]onky"`。 (3认同)

Bri*_*Guy 188

我使用的另一个选项(尤其是查看进程是否正在运行)是pgrep 命令。这将搜索匹配的进程,但不会列出搜索的 grep 行。我喜欢它,因为它是一种快速的搜索方式,无需正则表达式或转义任何内容。

pgrep fnord
Run Code Online (Sandbox Code Playgroud)

  • `ps | grep '[f]nord'` 既聪明又可敬,但 pgrep 是*正确的*。 (17认同)
  • 他们希望`-f` 选项更像`ps | grep`。 (11认同)
  • 还有一个 `-l` 参数可以让它显示正在匹配的命令。 (5认同)
  • 如果`pgrep 缺少选项,您总是可以执行`ps $(pgrep cmd) ...`(尽管它不适用于空命令集)。 (3认同)
  • @jordanm实际上,`pgrep -f`看起来更像是`ps -f | grep`。 (2认同)

RSF*_*on7 74

理想的解决方案是 BriGuy 提出的解决方案

pgrep fnord 
Run Code Online (Sandbox Code Playgroud)

但是如果你不想这样做,你可以排除所有与grep匹配的行:

ps aux | grep -v grep | grep "fnord"
Run Code Online (Sandbox Code Playgroud)

  • 但是如果我正在寻找的行是“bash bash grep bash”呢? (7认同)
  • @Sparr那么你应该使用最好的解决方案:`pgrep`或找到另一个;) (2认同)

Bra*_*sel 34

不是最优雅的解决方案,但您可以这样做:

$ ps aux | grep fnord | grep -v grep

  • 根据 https://superuser.com/a/409658/450260 你应该排除完整的 `grep fnord` 而不仅仅是 `grep` 即 `$ ps aux | grep fnord | grep -v“grep fnord”` (3认同)

Ema*_*erg 21

在 zsh 中,grep fnord =(ps aux).

这个想法是,首先运行ps aux,将结果放在一个文件中,然后grep在该文件上使用。只是,我们没有文件,因为我们使用 zsh 的“进程替换”。

为了说明,尝试

ps aux > ps.txt
grep fnord ps.txt
rm ps.txt
Run Code Online (Sandbox Code Playgroud)

结果应该是一样的。

对其他一些答案的一般性评论。有些太复杂和/或打字很长。这不仅是正确的问题,还应该是可用的。但这并不意味着其中一些解决方案不好;只是,它们必须封装在一个迷你 UI 中才能使用。

  • @PaŭloEbermann:并行是`<(command)`。`grep grep =(ps aux)` 不显示任何行。 (3认同)

Mor*_*gan 8

? 这个答案是特定于 GNU 的。有关更通用的解决方案,请参阅Wayne 的回答

搜索进程

如果您只是在寻找fnord进程,则可以使用-C按命令名称选择的选项:

ps -C fnord
Run Code Online (Sandbox Code Playgroud)

这可以根据您的喜好与 BSD 和 POSIX 风格的格式选项混合使用。有关完整列表,请参阅ps 手册页

寻找其他东西?

如果您需要比精确搜索命令名称更高级的东西,请不要放弃希望!这仍然可以ps在管道的一侧完成。我们所要做的就是告诉从结果中ps排除grep进程:

ps -NC grep | grep 'fnord'
Run Code Online (Sandbox Code Playgroud)

-C grep选择所有 grep 进程,并-N取消选择。这可用于搜索命令参数、命令名称的一部分或更复杂的正则表达式。

  • 这对 GNU `ps` 很好,但是 `-C` 不是由 POSIX 指定的,并且在 BSD 上具有完全不同的含义 (2认同)

yPh*_*hil 7

ps aux | grep $(echo fnord | sed "s/^\(.\)/[\1]/g")
Run Code Online (Sandbox Code Playgroud)

  • 这看起来像一个 IOCCC,但是对于 unix 命令行而不是 C ^^ 只是 `| grep $(echo fnord)` 还不够吗?您还要求 sed 搜索并用自己的值替换“fnord”中的每个字符?^^ 恭喜。我敢打赌我可以做一个更长的,但它可能不会那么有趣^^ (3认同)
  • @OlivierDulac:他不只是用自己的值替换第一个字符;他用方括号中的值的串联替换它。(那些方括号并不特殊,它们是字面意思。)基本上,他概括了 Wayne Werner 的答案,因此可以编写将方括号放在第一个字符周围的过程。+1 (3认同)
  • `ps辅助| grep '[^]]fnord'` 将避免这种体操。 (2认同)

Ada*_*atz 6

最简单的与 shell 无关的方法是首先将其存储在变量中:

PS_OUTPUT="$(ps aux)"; echo "$PS_OUTPUT" |grep fnord
Run Code Online (Sandbox Code Playgroud)

从我的 rc 文件中,我有一个不区分大小写的版本,它采用 grep 的选项:

psl() {
  local PS_OUTPUT="$(ps auxww)"
  echo "${PS_OUTPUT%%$'\n'*}" >&2  # title, in stderr to avoid pipes
  echo "${PS_OUTPUT#*$'\n'}" |grep -i "${@:-^}"
}
Run Code Online (Sandbox Code Playgroud)

代码遍历,每行代码一个项目符号:

  • 捕获详细ps输出(在local变量中,因此其范围仅限于函数)
  • 以标准错误显示第一行(标题),以便可以进一步过滤结果而不影响标题。替换表示:获取$PS_OUTPUT并删除第一个换行符之后的所有内容(正则表达式等效:)s/\n.*$//msg。这可以防止我们抓取标题
  • 显示除第一行之外ps的所有内容(正则表达式等效:) ,并使用 grep 其内容(不区分大小写)以及传递给此函数的所有选项(在没有模式的情况下,用于匹配每行的开头)s/^.*\n//m-i^

标注:@EmanuelBerg 的grep fnord =(ps aux)答案是迄今为止最优雅的,尽管它需要zsh. 我在 rc 文件中简短地包含了它,但 bash 抱怨该语法,即使有一个条件应该阻止它的评估。