Як читати певні рядки після знаходження тексту?


12

Як я можу прочитати певну кількість рядків після пошуку тексту?

Напр .:

Прочитайте наступні 2 рядки після пошуку "Unix" на:

Test 1
Test 2
Test 3
Test 4
UNIX
Test 5
Test 6
Test 7
Test 8
Test 9

Результат може бути:

Test 5
Test 6

Примітка: "Unix" в останньому прикладі є аргументом, і таким чином, це може бути будь-який інший текст.

Що я маю:

Я все ще не в ідеях, мені потрібно просто світло. Думаючи створити інший сценарій для цього.

Відповіді:


10

awkрішення:

$ awk '$0 == "UNIX" {i=1;next};i && i++ <= 2' file
Test 5
Test 6

Пояснення

  • /^UNIX$/{i=1;next}: якщо ми бачимо UNIX, ми встановлюємо змінну i = 1, обробляючи наступний вхід.

  • Якщо змінна iвстановлена ​​(означає, що ми бачили UNIX), вона i && i++ <= 2оцінюється до справжнього значення в наступних двох рядках після UNIX, викликаючи awkвиконані за замовчуванням дії print $0.

  • До того UNIX, як бачити , iне було визначено, а починати з 3-го рядка після цього UNIX, він iмав значення більше 2, завдяки чому вираз i && i++ <= 2оцінюється як хибне, не викликаючи awkнічого.


Після тестування ви вирішуєте, що отримуєте це повідомлення про помилку: система помилок біля рядка 1, викид біля лінії 1
Холодний

@Cold: Що ти запускав? Зверніть увагу, що $знак на початку моєї відповіді - це підказка оболонки, а не частина awkкоманди.
cuonglm

Ще один варіант:awk '/^UNIX$/ {s=NR;next} s && NR<=s+2'
musiphil

Я знаю, що @cuonglm
Холодний

@Cold: Яка ваша ОС?
cuonglm

12

grepрішення:

grep -A2 -P '^UNIX$' file

Пояснення: -A означає: надрукуйте наступні два рядки після відповідності

Або awk:

awk '$0=="UNIX"{getline; print; getline; print}' file

Пояснення: Цей оператор шукає UNIX у рядку ( $0=="UNIX"). Якщо це дано, він отримує наступний наступний у своєму буфері ( getline) та друкує буфер ( print). Це робиться двічі.

Або скористайтеся sed:

sed -n '/^UNIX$/{n;p;n;p}' file

Пояснення: Це схвалення для UNIX ( /^UNIX$/). Якщо це знайдено, він виконує частину в {...}. nозначає наступний, pозначає друк. Це також робиться вдвічі.


Дякую @chaos, я спробую останні два варіанти, які ви даєте. Запросимо додати пояснення кожного варіанту, і я повинен скласти і зробити.
Холодний

Якщо кількість рядків зміниться, скільки змін я внесу в останніх двох варіантах? Спасибі
Холодний

@Cold дивись мою редакцію Змінити число, якщо рядки повторюють getline; print;частину у awkвиписці або n;p;частину у sedвиписці.
хаос

Дякую @chaos, але чим більша кількість рядків - це посилення вираження, і зміна, на мою думку, неможливо. Ви не думаєте? Якщо 100 рядків?
Холодний

@Cold Тоді я б застосував греп-розчин із grep -A100 -P '^UNIX$' file | tail -n +2. Хвостова частина полягає у видаленні першого затяжної залози. В інших (sed, awk) вам доведеться писати петлі, що робить його менш простим.
хаос

4
grep -A 2 UNIX file.txt

Відображення grep описує варіант таким чином:

  -A NUM, --after-context=NUM
      Print NUM  lines  of  trailing  context  after  matching  lines.
      Places  a  line  containing  --  between  contiguous  groups  of
      matches.

Привіт @Twinkles, хороша відповідь, але мій греп має лише такі параметри "hblcnsviw". Але логіка хороша. дякую
Холодний

Це також буде надруковано UNIXна виході.
cuonglm

Щоб опустити UNIX, труби його tail: [...] | tail -n +1або sed: [...] | sed '1d'.
DopeGhoti

1
@DopeGhoti: ваші пропозиції tailта sed '1d'пропозиції працюють правильно лише в тому випадку, якщо вони UNIXвідображаються лише один раз у вхідному тексті. Усі інші відповіді дозволяють отримати кілька випадків. Можливо, краще підказати ... | grep -v UNIX. Справді, це стає безладним, якщо UNIXз’являється на лініях 15 та 17.
G-Man каже: «Відновити Моніку»

Хороші бали. Я майже впевнений, що це може бути зроблено sedз якоюсь формою sed '/UNIX/d;n;n;p/' /path/to/file, яку я просто затримав і подав як відповідь.
DopeGhoti

0

Це, здається, добре виконає трюк:

sed -n '/UNIX/{n;p;n;p}' /path/to/file

Доказ концепції:

$ for i in {1..9}; do echo $i; done | sed -n '/4/{n;p;n;p}'
5
6

1
Передня оболонка навколо вашого forциклу не потрібна.
Призупинено до подальшого повідомлення.

Дійсно, це не так; це був залишок якоїсь іншої фальшивки, у якій я був посеред цієї оболонки раніше дня. Парени вилучені.
DopeGhoti

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.