Друкувати відповідну лінію та n-й рядок із відповідної лінії


18

Я намагаюся надрукувати відповідні рядки та 4-й рядок із відповідного рядка (рядок, що містить вираз, який я шукаю).

Я використовував такий код: sed -n 's/^[ \t]*//; /img class=\"devil_icon/,4p' input.txt

Але це тільки друкує зіставлену лінію.

Це друкує лише 4-й рядок. awk 'c&&!--c;/img class=\"devil_icon/{c=4}' input.txt

Мені потрібно надрукувати як відповідні рядки, так і 4-й рядок.


Використання egrep "pattern" -A4
Валентин Байрамі

@ val0x00ff, який друкує рядки між ними .. тобто: він друкує наступні 4 рядки, починаючи з відповідного рядка
debal

ви говорите: "Я намагаюся надрукувати відповідні рядки та 4-й рядок із відповідного рядка". Це grep -A 4 "pattern" file | sed -n '4p'робить саме те, що ви хочете, якщо тільки я вас не розумію
Валентин Байрамі

ні, це не так. Вихід з вищевказаного коду був </td>не четвертим рядком
дебал

Відповіді:


18

Будь-ласка, ви зробите це наступним чином

awk '/pattern/{nr[NR]; nr[NR+4]}; NR in nr' file > new_file`

або

awk '/pattern/{print; nr[NR+4]; next}; NR in nr' file > new_file`

Пояснення

Перше рішення знаходить усі рядки, які відповідають pattern. Коли він знаходить відповідність, він зберігає номер запису ( NR) у масиві nr. Він також зберігає 4-й запис з NRтого ж масиву. Це робиться nr[NR+4]. Кожен запис ( NR) перевіряється, чи він присутній у nrмасиві, якщо так записаний запис.

Друге рішення працює по суті таким же чином, за винятком випадків, коли він стикається, patternвін друкує цей рядок, а потім зберігає четвертий запис попереду нього в масиві nr, а потім переходить до наступного запису. Тоді, коли awkзустрінеться з цією четвертою записом, NR in nrблок буде виконаний та надрукує цю запис +4 після цього.

Приклад

Ось файл даних , наприклад sample.txt.

$ cat sample.txt 
1
2
3
4 blah
5
6
7
8
9
10 blah
11
12
13
14
15
16

Використання 1-го рішення:

$ awk '/blah/{nr[NR]; nr[NR+4]}; NR in nr' sample.txt 
4 blah
8
10 blah
14

Використання 2-го рішення:

$ awk '/blah/{print; nr[NR+4]; next}; NR in nr' sample.txt 
4 blah
8
10 blah
14

3
Приємно, +1. Ви використовуєте тут багато awkярликів, чи можете ви додати коротке пояснення (такі речі, як друк, що мається на увазі в awk, і що масиви асоціативні тощо)?
terdon

згода з @terdon, будь ласка, чи можете ви трохи пояснити код.
дебал

@slm Дякую за вдосконалення та надання повної відповіді!
Валентин Байрамі

1
Дякую за відповідь, і я навчився чогось нового з цим.
slm

4
sed -n 's/^[ \t]*/; /img class=\"devil_icon/,+4 { 3,5d ; p }' input.txt

Я просто додаю видалення відповідних рядків перед друком { 3,5d ; p }.


ваш вираз створює помилку: sed: -e expression #1, char 18: unknown option to s'`
мінерали

4

Ви можете спробувати -Aваріант з grep, який вказує, скільки рядків після відповідного рядка має бути надруковано. З'єднайте це sed, і ви отримаєте потрібні лінії.

grep -A 4 pattern input.txt | sed -e '2,4d'

Використовуючи sed, ми видаляємо з другого рядка до четвертого.


3
Це передбачає один збіг patternу файлі.
terdon

2

Ось спосіб у Perl, який може мати справу з довільною кількістю відповідних рядків:

perl -ne '/pattern/ && do{$c=$.; print}; $.==$c+4 && print' file > new_file`

У Perl. спеціальна змінна $.- номер поточного рядка. Отже, кожного разу, коли знаходжу відповідність рядка pattern, я роздруковую її і зберігаю її номер як $c. Потім я знову друкую, коли номер поточного рядка на 4 більше, ніж той, який був надрукований раніше.


0
awk 'c&&!--c;/img class=\"devil_icon/{c=4};/img class=\"devil_icon/' input.txt

Ви по суті робите пошук і заміну. Ви можете додати просто знахідку до однієї команди, і вона надрукує їх обох :)

awk 'c&&!--c;/pattern/{c=4};/pattern/' input.txt
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.