использование grep для фильтрации потока строк и добавления к нему префикса обнаруженного шаблона

получил каверзный вопрос относительно фильтрации нескольких шаблонов с помощью 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, сед и т. д.)

для меня важно сделать это очень быстро и эффективно, поэтому я не хочу заморачиваться с циклами и множественными вызовами различных исполняемых инструментов Linux.

хочу, чтобы он обрабатывался как поток с помощью одного инструмента, который выполняет фильтрацию по нескольким параметрам, а также сообщает мне, какой из шаблонов он выбрал


person tal shachar    schedule 15.02.2018    source источник
comment
пожалуйста, добавьте ожидаемый результат, чтобы уточнить ваши требования...   -  person Sundeep    schedule 15.02.2018


Ответы (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
  • В основном блоке мы проверяем, содержит ли строка какое-либо ключевое слово, а затем добавляем к строке префикс этого ключевого слова.
person anubhava    schedule 15.02.2018
comment
работает хорошо. именно то, что мне было нужно. было ощущение, что awk может сделать свое дело. но я почти не знаю синтаксиса, кроме обычного вывода этой суммы, что в среднем это мамбо-джамбо. большое спасибо - person tal shachar; 15.02.2018

Я думаю, это то, что вы ищете:

$ 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

Это захватывает совпадающую строку и добавляет ее в начало совпадающей строки.

person Sundeep    schedule 15.02.2018

Другой авк:

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

Укажите шаблон поиска в переменной s. Он поддерживает только первое совпадение в строке, но легко расширяется, чтобы показать их все.

person James Brown    schedule 15.02.2018