Как показать только следующую строку после совпавшей?

218
grep -A1 'blah' logfile

Благодаря этой команде для каждой строки, содержащей «бла», я получаю вывод строки, содержащей «бла», и следующую строку в лог-файле. Это может быть простой, но я не могу найти способ пропустить строку, которая имеет «бла» и показать только следующую строку в выводе.

Facha
источник
72
Я думаю, что многие люди придут сюда в поисках -A1варианта
Mirelon
Затем я использую это, чтобы получить мой публичный IP. :)curl whatismyip.org | grep -A1 'Your IP Address'
shrekuu
6
Аналогично -B1, -B2, -B3, -A1, -A2, -A3. , ,
Meawoppl
5
@shrek curl icanhazip.com (без необходимости grep) :)
alexyorke
1
Ваш вопрос ответил на мой вопрос ... -A1. Спасибо!
S3DEV

Ответы:

181

вы можете попробовать с awk:

awk '/blah/{getline; print}' logfile
Михал Шрайер
источник
3
Для тех, кто действительно хотел получить эквивалент grep -A2 (что мне и было нужно), getline просто ест строку и переходит к следующему. То, что сработало для меня, было буквально простоawk '/blah/{getline; getline; print}' logfile
Аарон Р.
160

если вы хотите придерживаться grep:

grep -A1 'blah' logfile|grep -v "blah"

или

sed -n '/blah/{n;p;}' logfile
Кент
источник
2
@Kent, спасибо за совет. Из моего POV, хотя, grep гораздо более читабелен и его легко понять, по сравнению с sed или awk-ответом, помеченным как лучший ответ .... но это может быть только я :)
icasimpan
2
Для тех, кому интересно, что делает -v: -v --invert-match Инвертировать смысл соответствия, чтобы выбрать несовпадающие строки. (-v определяется POSIX.)
Сэмми,
2
Мне очень нравится этот ответ, но он не будет работать, если у вас есть две строки подряд, содержащие «бла», и вы хотите получить вторую (потому что это «следующая строка после совпавшей»). Я не могу придумать ни одного варианта использования для этого на макушке, но это стоит отметить.
Tin Wizard
Лучшее решение просто "хорошо". Если во второй строке тоже есть «бла», у вас в руках будет настоящий беспорядок.
riwalk
32

Трубка - твой друг ...

Используйте, grep -A1чтобы показать следующую строку после матча, затем направить результат tailи захватить только 1 строку,

cat logs/info.log | grep "term" -A1 | tail -n 1
weisjohn
источник
1
Если «term» находится в последней строке, это вернет строку, содержащую «term» вместо ничего, что вы хотели бы.
Аноним
tail -n 1 приведет только к последней строке всего файла
Себастьян
13

Отличный ответ от raim, был очень полезен для меня. Это тривиально расширить, чтобы напечатать, например, строку 7 после шаблона

awk -v lines=7 '/blah/ {for(i=lines;i;--i)getline; print $0 }' logfile
Сутер
источник
9

Если эти следующие строки никогда не содержат «бла», вы можете отфильтровать их с помощью:

grep -A1 blah logfile | grep -v blah

Использование cat logfile | ...не требуется.

ott--
источник
5

В общем, я согласен, что вы спрашиваете много о grep, и что другой инструмент может быть лучшим решением. Но во встроенной среде я могу не захотеть sedили awkпросто делать это. Я обнаружил, что работает следующее решение (если они не являются смежными):

grep -A1 AT\+CSQ wvdial.out | grep -v AT\+CSQ

По сути, сопоставьте их, добавив 1 строку контекста для каждого совпадения, а затем передайте это через обратное совпадение с вашим исходным шаблоном, чтобы удалить их. Это, конечно, означает, что вы можете предположить, что ваш шаблон не отображается в «следующей» строке.

Трэвис Григгс
источник
5

До сих пор было дано много хороших ответов на этот вопрос, но я все еще скучаю по одному из них, awkне используя getline. Так как, в общем-то , использовать не нужно getline, я бы пошел на:

awk ' f && NR==f+1; /blah/ {f=NR}' file  #all matches after "blah"

или

awk '/blah/ {f=NR} f && NR==f+1' file   #matches after "blah" not being also "blah"

Логика всегда заключается в сохранении строки, в которой находится «бла», и последующей печати строк, следующих за одной строкой.

Тест

Образец файла:

$ cat a
0
blah1
1
2
3
blah2
4
5
6
blah3
blah4
7

Получить все строки после "бла". Это печатает другой "бла", если он появляется после первого.

$ awk 'f&&NR==f+1; /blah/ {f=NR}' a
1
4
blah4
7

Получить все строки после "бла", если они не содержат "бла" сами.

$ awk '/blah/ {f=NR} f && NR==f+1' a
1
4
7
Федорки "ТАК прекратить вредить"
источник
5

Я не знаю ни одного способа сделать это с помощью grep, но можно использовать awk для достижения того же результата:

awk '/blah/ {getline;print}' < logfile
raimue
источник
@jww Разницы нет. Как вы можете видеть из отметок времени, которые находятся на расстоянии нескольких минут, кажется, что я ответил примерно в то же время.
Рэйм
4

Perl однострочное оповещение

просто для удовольствия ... печатать только одну строку после матча

perl -lne '$next=($.+1)if/match/;$.==$next&&print' data.txt

еще веселее ... печатать следующие десять строк после матча

perl -lne 'push@nexts,(($.+1)..($.+10))if/match/;$.~~@nexts&&print' data.txt

своего рода обман, хотя, так как на самом деле есть две команды

beasy
источник
Можете ли вы объяснить $. == $ дальше? Ясно, что это больше, чем числовое сравнение текущего номера строки с $ next, но я не понимаю, как / почему это работает.
Кит Бентруп
Это не более того. $. == $next && printтак же, какprint if $. == $next
beasy
Ах, теперь я вижу. Спасибо! Каждая из двух частей имеет значение true и выполняется на отдельных смежных итерациях цикла. Я предполагаю, что если бы целью было напечатать любую строку после любого соответствия, которое вы хотели бы изменить в обратном порядке (будет вести себя больше как grep -A1). Если вы хотите печатать только следующие строки, но не строку с соответствием, то вы должны оставить это в таком порядке. (просто отмечая, как $ next будет перекрыт для последовательных матчей)
Кит Бентруп
3

Похоже, вы используете не тот инструмент. Grep не так уж и сложен, я думаю, вы хотите использовать awk как инструмент для работы:

awk '/blah/ { getline; print $0 }' logfile

Если у вас возникнут проблемы, дайте мне знать, я думаю, что стоит изучить немного awk, это отличный инструмент :)

ps Этот пример не выигрывает «бесполезное использование награды кошки»;) http://porkmail.org/era/unix/award.html

sillyMunky
источник
3
Кстати, вы можете пропустить "$ 0" в печати.
Михал Шрайер
0

grep / Pattern / | tail -n 2 | голова -n 1

Хвост сначала 2, а затем возглавляй последний, чтобы получить ровно первую строчку после матча.

Амрит Пал Сингх
источник