2

在根据所选模式修改流本身时,遇到了一个关于使用 grep 过滤多个模式的棘手问题

如果我想过滤让我们说“ps -ef”输出的多种模式,我可以这样做

ps -ef |grep -E "client|postgres:"

postgres 142705   3845  0 12:04 ?        00:00:00 postgres: suiteadmin suiteadmin 127.0.0.1(34380) idle
postgres 142979   3845  3 12:04 ?        00:00:00 postgres: cost securetrack [local] idle
postgres 142989   3845 12 12:04 ?        00:00:00 postgres: cost securetrack [local] SELECT
root     142991 140798  0 12:04 pts/0    00:00:00 my.client -fce

但是,我无法在流处理的后面判断“客户端”或“postgres:”模式是否与特定流线匹配(这对我的用例至关重要)

如果我选择使用 -o 参数,grep 会从我请求的多个模式中为我提供实际匹配的模式,但它不会打印它在其中找到模式的整个流线(我也需要)

ps -ef |grep -Eo "client|postgres:"
postgres:
postgres:
postgres:
client

我希望 grep (或可能是另一个工具)给我“匹配模式”+“匹配模式的行”,这样我以后可以将它作为一个流处理,知道“为什么”它首先被选中。

不太确定我可以用 grep 做到这一点是否有其他工具可以用于此?(awk、sed 等...)

对我来说非常快速和高效地完成它很重要,所以我不想开始搞乱循环和对不同 linux 可执行工具的多次调用

希望使用一个工具将其作为流处理,该工具既可以通过多个选项进行过滤,也可以告诉我它选择了哪个模式

4

3 回答 3

3

您可以awk为此使用:

ps -ef | 
awk -v kw='client;postgres:' 'BEGIN{n=split(kw, a, /;/)} {
for (i=1; i<=n; i++) if ($0 ~ a[i]) print a[i] "#", $0}'

postgres:# postgres 142705   3845  0 12:04 ?        00:00:00 postgres: suiteadmin suiteadmin 127.0.0.1(34380) idle
postgres:# postgres 142979   3845  3 12:04 ?        00:00:00 postgres: cost securetrack [local] idle
postgres:# postgres 142989   3845 12 12:04 ?        00:00:00 postgres: cost securetrack [local] SELECT
client# root     142991 140798  0 12:04 pts/0    00:00:00 my.client -fce
  • 使用-v kw='client;postgres:'我们传递一个;分隔的关键字来搜索ps输出
  • 使用split函数我们将列表拆分为一个数组a
  • 在主块中,我们检查一行是否包含任何关键字,然后我们在该行前面加上该关键字
于 2018-02-15T10:20:14.240 回答
2

我认为这就是你要找的:

$ ps -ef | sed -nE 's/.*(client|postgres:).*/\1 &/p'
postgres: postgres 142705   3845  0 12:04 ?        00:00:00 postgres: suiteadmin suiteadmin 127.0.0.1(34380) idle
postgres: postgres 142979   3845  3 12:04 ?        00:00:00 postgres: cost securetrack [local] idle
postgres: postgres 142989   3845 12 12:04 ?        00:00:00 postgres: cost securetrack [local] SELECT
client root     142991 140798  0 12:04 pts/0    00:00:00 my.client -fce

这将捕获匹配的字符串并将其添加到匹配行的开头

于 2018-02-15T10:19:36.880 回答
1

另一个awk:

$ echo foo bar | 
awk -v s="bar|baz" '$0~s{match($0,s);print substr($0,RSTART, RLENGTH) ":", $0}'
bar: foo bar

s在变量中给出搜索模式。它只支持第一个匹配,但很容易扩展以显示它们。

于 2018-02-15T10:23:12.937 回答