如何管道 grep 并保留标题?

如何管道 grep 并保留标题?

在下面的示例中,我有正确的选择,但没有标题,反之亦然。我怎样才能两者兼得?

$ ps aux | grep 'gpart'
erwann    200603  0.0  0.0   2608    72 pts/3    S    12:57   0:00 /bin/sh /usr/sbin/gparted
root      200608  0.0  0.0   2608  1056 pts/3    S    12:57   0:00 /bin/sh /usr/sbin/gparted
root      200693  0.0  0.0   2608    68 pts/3    S    12:57   0:00 /bin/sh /usr/lib/udisks2/udisks2-inhibit /usr/sbin/gpartedbin
root      200700  1.9  0.2 264960 18620 pts/3    SLl  12:57   8:31 /usr/sbin/gpartedbin
root      202327 99.8  0.0   2520    64 pts/3    R    13:36 400:07 gpart -s 512 /dev/sdc
erwann    214723  0.0  0.0   9032   716 pts/4    S+   20:17   0:00 grep --color=auto gpart
$ ps aux | tee >(head -n1) >(grep 'gpart') > /dev/null
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND

答案1

如果您想要搜索固定字符串,gpart您可以使用 的多重匹配变体grep来挑选匹配行以及第一行本身:

ps aux | grep -E '^USER|[g]part'

awk或者,使用输出第一行和与模式匹配的任何行的解决方案:

ps aux | awk 'NR==1 || /[g]part/'

在这两种情况下, 的第一个字符gpart都位于方括号中,因为这会阻止grepawk匹配自身。 (正则表达式中包含单个字符的方括号实际上是一个无操作,仅表示单个字符本身。)

示例(基于ps您问题中显示的输出)

ps aux | grep -E '^USER|[g]part'
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
erwann    200603  0.0  0.0   2608    72 pts/3    S    12:57   0:00 /bin/sh /usr/sbin/gparted
root      200608  0.0  0.0   2608  1056 pts/3    S    12:57   0:00 /bin/sh /usr/sbin/gparted
root      200693  0.0  0.0   2608    68 pts/3    S    12:57   0:00 /bin/sh /usr/lib/udisks2/udisks2-inhibit /usr/sbin/gpartedbin
root      200700  1.9  0.2 264960 18620 pts/3    SLl  12:57   8:31 /usr/sbin/gpartedbin
root      202327 99.8  0.0   2520    64 pts/3    R    13:36 400:07 gpart -s 512 /dev/sdc

答案2

如果与正在运行的实际命令(即/proc/PID/comm而不是/proc/PID/cmdline在 Linux 上)完全匹配是可以的,请尝试ps-C选项。例如:

ps u -C gpart

man ps

-C cmdlist

按命令名称选择。这将选择 cmdlist 中给出的可执行名称的进程。注意:命令名称与命令行不同。以前版本的 procps 和内核将此命令名称截断为 15 个字符。两者都不再存在此限制。如果您仅依赖于匹配 15 个字符,则可能不再获得匹配项。

这将显示程序的标题和详细信息gpart,但不显示gparted程序,类似于以下内容(这是准确的,但合成输出部分从您的问题复制粘贴,因为我实际上并未gpart在我的系统上运行)。

$ ps u -C gpart
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root      202327 99.8  0.0   2520    64 pts/3    R    13:36 400:07 gpart -s 512 /dev/sdc

顺便说一句,cmdlist可以是单个命令名称或以逗号分隔的命令名称列表。例如ps u -C gpart,gparted


另外顺便说一句,您可以将其与其他ps选项结合起来。例如,如果您想要的只是进程的 PID gpart

ps ho pid -C gpart

h抑制标头,o pid仅输出 PID。

甚至:

GPART_PID=$(ps ho pid -C gpart)

答案3

如果您指的是这两行,则为以下任一行:

ps aux | egrep "^USER.*COMMAND|gpart"

px aux | grep -E "^USER.*COMMAND|gpart"

ps aux | awk '/^USER.*COMMAND/ || /gpart/'

如果您不想匹配包含命令本身的行:

ps aux | egrep "^USER.*COMMAND|[g]part"

px aux | grep -E "^USER.*COMMAND|[g]part"

ps aux | awk '/^USER.*COMMAND/ || /[g]part/'

每个系列中的前两个命令用于grep返回带有“标题”的任何行以及带有字符串的任何其他行gpart,最后一个命令用于awk执行相同的操作。

没有任何理由使用该命令,tee因为其他命令也这样做并且不太复杂。

相关内容