Хороший спосіб
Зазвичай ви не можете зробити це з 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т. Ін. Популярна: деталі важливо скласти в цілісне ціле.