Хороший спосіб
Зазвичай ви не можете зробити це з grep, але ви можете використовувати інші інструменти. Про AWK вже згадувалося, але ви також можете користуватися sed
таким чином:
sed -e '1p' -e '/youpattern/!d'
Як це працює:
Утиліта Sed працює на кожному рядку індивідуально, виконуючи вказані команди на кожному з них. Ви можете мати кілька команд, вказавши кілька -e
варіантів. Ми можемо додати кожній команді параметр діапазону, який визначає, чи слід застосовувати цю команду до певного рядка чи ні.
"1p" - перша команда. Він використовує p
команду, яка зазвичай друкує всі рядки. Але ми додаємо його до числового значення, яке визначає діапазон, до якого він повинен застосовуватися. Тут ми використовуємо, 1
що означає перший рядок. Якщо ви хочете надрукувати більше рядків, ви можете використовувати x,yp
там, де x
друкується перший рядок, y
- це останній рядок для друку. Наприклад, щоб надрукувати перші 3 рядки, ви б використовували1,3p
Наступна команда, d
яка зазвичай видаляє всі рядки з буфера. Перед цією командою ми ставимо yourpattern
між двома /
символами. Це інший спосіб (спочатку було вказати, у яких рядках, як ми це робили з p
командою) адресних рядків, над якими повинна працювати команда. Це означає, що команда працюватиме лише для рядків, які відповідають yourpattern
. За винятком того, що ми використовуємо !
символ перед d
командою, яка інвертує його логіку. Тож тепер він видалить усі рядки, які не відповідають заданому шаблону.
Наприкінці sed буде надрукувати всі рядки, які залишилися в буфері. Але ми видалили рядки, які не збігаються з буфера, тому будуть надруковані лише відповідні рядки.
Підводячи підсумок: ми друкуємо перший рядок, потім видаляємо всі рядки, які не відповідають нашому шаблону, із введення. Решта рядків друкуються (тому лише рядки, які відповідають шаблону).
Проблема першого рядка
Як зазначалося в коментарях, існує проблема з цим підходом. Якщо вказаний шаблон відповідає також першому рядку, він буде надрукований двічі (один раз за p
командою та один раз через збіг). Ми можемо уникнути цього двома способами:
Додавання 1d
команди після 1p
. Як я вже згадував, d
команда видаляє рядки з буфера, і ми вказуємо його діапазон за номером 1, а це означає, що вона видалить лише 1-й рядок. Отже команда була бsed -e '1p' -e '1d' -e '/youpattern/!d'
Використовуючи 1b
команду замість 1p
. Це хитрість. b
команда дозволяє переходити до іншої команди, визначеної міткою (таким чином деякі команди можна опустити). Але якщо ця мітка не вказана (як у нашому прикладі), вона просто переходить до кінця команд, ігноруючи решту команд для нашого рядка. Тож у нашому випадку остання d
команда не видалить цей рядок із буфера.
Повний приклад:
ps aux | sed -e '1b' -e '/syslog/!d'
Використання крапки з комою
Деякі sed
реалізації можуть заощадити певний текст, використовуючи крапку з комою для розділення команд замість декількох -e
варіантів. Тож якщо вам не байдуже бути портативними, команда була б ps aux | sed '1b;/syslog/!d'
. Він працює принаймні в GNU sed
та busybox
реалізаціях.
Божевільний шлях
Ось, однак, досить шалений спосіб зробити це з грепом. Це, безумовно, не оптимально, я розміщую це лише для навчальних цілей, але ви можете використовувати його, наприклад, якщо у вас немає жодного іншого інструменту у вашій системі:
ps aux | grep -n '.*' | grep -e '\(^1:\)\|syslog'
Як це працює
Спочатку ми використовуємо -n
опцію для додавання номерів рядків перед кожним рядком. Ми хочемо нумерувати всі рядки, які ми співставляємо .*
- що завгодно, навіть порожній рядок. Як запропоновано в коментарях, ми також можемо відповідати "^", результат такий же.
Тоді ми використовуємо розширені регулярні вирази, щоб ми могли використовувати \|
спеціальний символ, який працює як АБО. Тож ми співставляємось, якщо рядок починається з 1:
(перший рядок) або містить наш шаблон (у даному випадку його syslog
).
Проблема чисел рядків
Тепер проблема полягає в тому, що ми отримуємо ці потворні номери рядків у нашому виході. Якщо це проблема, ми можемо їх усунути cut
, як-от так:
ps aux | grep -n '.*' | grep -e '\(^1:\)\|syslog' | cut -d ':' -f2-
-d
опція вказує роздільник, -f
вказує поля (або стовпці), які ми хочемо надрукувати. Отже, ми хочемо вирізати кожен рядок на кожному :
символі та надрукувати лише 2-й та всі наступні стовпці. Це ефективно видаляє перший стовпчик з його роздільником, і саме це нам і потрібно.
ack
настільки корисні, і чому популярністьperl
минулогоsed
іawk
т. Ін. Популярна: деталі важливо скласти в цілісне ціле.