Предполагая простой grep, такой как:
$ psa aux | grep someApp
1000 11634 51.2 0.1 32824 9112 pts/1 SN+ 13:24 7:49 someApp
Это дает много информации, но поскольку первая строка команды ps отсутствует, контекст для информации отсутствует. Я бы предпочел, чтобы первая строка ps была также показана:
$ psa aux | someMagic someApp
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
1000 11634 51.2 0.1 32824 9112 pts/1 SN+ 13:24 7:49 someApp
Конечно, я мог бы добавить регулярное выражение в grep специально для PS:
$ ps aux | grep -E "COMMAND|someApp"
Тем не менее, я бы предпочел более общее решение, поскольку есть и другие случаи, в которых я хотел бы также иметь первую строку.
Похоже, это было бы хорошим вариантом использования дескриптора файла "stdmeta" .
bash
command-line
dotancohen
источник
источник
ack
так полезны, и почемуperl
взлетела в прошломsed
,awk
и т.д. в популярности: это важно для части , чтобы подвести итог в единое целое.-C
аргумент to,ps
и вам не нужно будет передавать его в grep. например,ps u -C someApp
или дажеps u -C app1 -C app2 -C app3
ps aux | { head -1; grep foo; }
Что-то вроде обобщенной версии, упомянутой @Nahuel Fouilleul ниже (его, вероятно, единственное решение, которое я мог бы вспомнить на месте, если это необходимо)Ответы:
Хороший способ
Обычно вы не можете сделать это с помощью grep, но вы можете использовать другие инструменты. AWK уже упоминался, но вы также можете использовать
sed
, как это:Как это устроено:
Утилита Sed работает в каждой строке индивидуально, выполняя указанные команды для каждой из них. Вы можете иметь несколько команд, указав несколько
-e
параметров. Мы можем добавить к каждой команде параметр диапазона, который указывает, должна ли эта команда применяться к определенной строке или нет.«1p» - это первая команда. Он использует
p
команду, которая обычно печатает все строки. Но мы добавляем к нему числовое значение, которое указывает диапазон, к которому он должен применяться. Здесь мы используем,1
что означает первую строку. Если вы хотите напечатать больше строк, вы можете использоватьx,yp
гдеx
первая строка для печати,y
последняя строка для печати. Например, чтобы напечатать первые 3 строки, вы должны использовать1,3p
Следующая команда,
d
которая обычно удаляет все строки из буфера. Перед этой командой мы ставимyourpattern
между двумя/
символами. Это другой способ (сначала было указать, какие строки, как мы делали сp
командой) адресации строк, на которых должна выполняться команда. Это означает, что команда будет работать только для совпадающих строкyourpattern
. Кроме того, мы используем!
символ передd
командой, которая инвертирует его логику. Так что теперь он удалит все строки, которые не соответствуют указанному шаблону.В конце sed напечатает все строки, которые остались в буфере. Но мы удалили строки, которые не совпадают из буфера, поэтому будут напечатаны только совпадающие строки.
Подводя итог: мы печатаем 1-ю строку, затем удаляем из строки все строки, которые не соответствуют нашему шаблону. Остальные строки печатаются (так только те строки , которые делают соответствовать шаблону).
Проблема с первой линией
Как уже упоминалось в комментариях, существует проблема с этим подходом. Если указанный шаблон соответствует также первой строке, он будет напечатан дважды (один раз по
p
команде и один раз из-за совпадения). Мы можем избежать этого двумя способами:Добавление
1d
команды после1p
. Как я уже упоминал,d
команда удаляет строки из буфера, и мы указываем его диапазон номером 1, что означает, что он будет удалять только 1-ю строку. Таким образом, команда будетsed -e '1p' -e '1d' -e '/youpattern/!d'
Используя
1b
команду вместо1p
. Это трюк.b
Команда позволяет нам перейти к другой команде, указанной меткой (таким образом, некоторые команды могут быть опущены). Но если эта метка не указана (как в нашем примере), она просто переходит к концу команд, игнорируя остальные команды для нашей строки. Так что в нашем случае последняяd
команда не удалит эту строку из буфера.Полный пример:
Используя точку с запятой
Некоторые
sed
реализации могут сэкономить вам ввод текста, используя точку с запятой для разделения команд вместо использования нескольких-e
параметров. Так что если вы не заботитесь о переносимости, команда будетps aux | sed '1b;/syslog/!d'
. Он работает по крайней мере вGNU sed
иbusybox
реализации.Сумасшедший путь
Вот, однако, довольно сумасшедший способ сделать это с помощью grep. Это определенно не оптимально, я публикую это только для целей обучения, но вы можете использовать его, например, если у вас нет другого инструмента в вашей системе:
Как это устроено
Сначала мы используем
-n
опцию, чтобы добавить номера строк перед каждой строкой. Мы хотим пронумеровать все строки, которые нам соответствуют,.*
что угодно, даже пустую строку. Как предлагается в комментариях, мы также можем сопоставить '^', результат тот же.Затем мы используем расширенные регулярные выражения, чтобы мы могли использовать
\|
специальный символ, который работает как OR. Таким образом, мы сопоставляем, если строка начинается с1:
(первая строка) или содержит наш шаблон (в данном случае егоsyslog
).Проблема с номерами строк
Теперь проблема в том, что мы получаем эти ужасные номера строк в нашем выводе. Если это проблема, мы можем удалить их
cut
следующим образом:-d
Параметр указывает разделитель,-f
указывает поля (или столбцы), которые мы хотим напечатать. Поэтому мы хотим разрезать каждую строку на каждом:
символе и печатать только 2-й и все последующие столбцы. Это эффективно удаляет первый столбец с его разделителем, и это именно то, что нам нужно.источник
cat -n
таким же успехом и выглядит более понятной, чем с использованием grep для этого.nl
не считает пустые строки (но печатает их без номера строки),cat -n
форматирует нумерацию с предшествующими пробелами,grep -n .
вообще удаляет пустые строки и добавляет двоеточие. У всех есть свои ... э ... особенности ;-)ps aux | sed '1p;/pattern/!d'
напечатает первую строку дважды, если она соответствует шаблону . Лучше всего использовалb
команду:ps aux | sed -e 1b -e '/pattern/!d'
.cat -n
это не POSIX.grep -n '^'
будет нумеровать каждую строку (не проблема для вывода ps, в котором нет пустых строк).nl -ba -d $'\n'
нумерует каждую строку.1b;...
это не переносимый и не POSIX, после «b» не может быть никаких других команд, поэтому вам нужен перевод строки или другое выражение -e.Как вы относитесь к использованию
awk
вместоgrep
?NR == 1
: Номер записи == 1; то есть. первая строка||
: или же:/syslogd/
: Шаблон для поискаНа это также стоит обратить внимание
pgrep
, хотя это скорее для сценариев, а не для вывода пользователем. Однако она не позволяет самойgrep
команде появляться в выходных данных.источник
РЕДАКТИРОВАТЬ: после комментариев
Я
head -1
бы хоть прочитал весь ввод, но после тестирования он тоже работает.выход
источник
{ IFS='' read line; ... }
если заголовок начинается с пробелов.head -1
вместо комбо чтения / эха.head -n1
моим Bash. Это, вероятно, может зависеть от реализации. Моя голова не читает весь ввод в этом случае, только первую строку, оставляя их в буфере ввода.head -n1
короче, но, похоже, даже спецификация POSIX ничего не говорит о том, сколько входных данных ему разрешено читать, так что, возможноread line; echo $line
, все-таки более переносимо.Ps поддерживает внутренний фильтр,
Предположим, вы ищете процесс bash:
ps -C bash -f
Перечислим все процессы, которые названы
bash
.источник
Я склонен отправлять заголовок в stderr :
Обычно этого достаточно для чтения человеком. например:
Часть в скобках может войти в собственный сценарий для общего пользования.
Есть дополнительное удобство в том, что вывод может быть далее передан по каналу (в
sort
и т. Д.), А заголовок останется сверху.источник
Вы также можете использовать
tee
иhead
:Однако обратите внимание, что до тех пор, пока
tee
он не может игнорироватьSIGPIPE
сигналы (см., Например, обсуждение здесь ), этот подход требует обходного пути, чтобы быть надежным. Обходной путь должен игнорировать сигналы SIGPIPE, например, это может быть сделано в bash как оболочки:Также обратите внимание, что порядок вывода не гарантируется .
источник
grep
:| { sleep .5; cat }
.Возможно, две
ps
команды будут самыми легкими.источник
ps aux
вызовом ... И если вы просто хотите эту статическую первую строку, почему бы не повторить его вручную?Вы можете использовать pidstat с:
Пример:
Дополнительная информация: http://linux.die.net/man/1/pidstat
источник
Поместите следующее в ваш файл .bashrc или сначала скопируйте / вставьте в оболочку для тестирования.
Использование: psls [grep pattern]
Убедитесь, что ваш источник .bashrc (или .bash_profile, если вы положили его туда):
Функция даже автоматически завершится в командной строке оболочки. Как вы указали в другом ответе, вы можете направить первую строку в файл, чтобы сохранить один вызов в ps.
источник
psl
, которая только звонитьps
иgrep
один раз (и не нужноhead
).сортировать, но держать строку заголовка вверху
И используйте это так
источник
В основном благодаря Janis Papanagnou в comp.unix.shell, я использую следующую функцию:
Это имеет ряд преимуществ:
-i
для сопоставления без учета регистра,-E
для расширенных регулярных выражений и т. Д.Пример использования:
источник
Еще один способ с
gnu ed
:или, если оболочка поддерживает подстановку процесса:
это:
Более переносимый, без
gnu
'!'
замены или подстановки оболочки - использование толькоed
встроенного,r
чтобыr
перевести выходные данныеps aux
в буфер, а затем удалить несовпадающие строки в2,$
диапазоне и вывести результат:И так как
sed
команды в принятом ответе выводят также совпадающую строку, сsed
поддержкой, которая поддерживает,-f-
и оболочкой, которая поддерживает замену процесса, я бы запустил:который в значительной степени делает то же самое, что и предыдущие
ed
команды.источник
Perl путь:
Гораздо проще читать, чем
sed
быстрее, без риска выбрать нежелательные строки.источник
Если это только для процессов поиска с полными заголовками, я бы расширил предложение @ mrb:
pgrep bash | xargs ps -fp
получит тот же результат, но без подоболочки. Если требуется другое форматирование:источник
Если вы знаете точные номера строк, это легко сделать с помощью Perl! Если вы хотите получить строки 1 и 5 из файла, скажите / etc / passwd:
Если вы хотите получить и другие строки, просто добавьте их номера в массив.
источник