Печать строки после n-го совпадения


8

Я ищу, чтобы отобразить строку 4598 в следующем файле. По сути, я хочу отобразить строку ПОСЛЕ n-го вхождения совпадения. В этом случае строка после 3-го появления <Car>. Как мне это сделать?

<Car>
10456
</Car>
<Car>
70192
</Car>
<Car>
4598
</Car>

1
Хотя может быть возможно достичь того, что вы хотите, используя sed, awkили даже grep, желательно использовать синтаксический анализатор XML.
— devnull

XML использовался только для примера, текст может быть любого формата
— DJ180

Ответы:


10
awk -v n=3 '/<Car>/ && !--n {getline; print; exit}'

Или:

awk '/<Car>/ && ++n == 3 {getline; print; exit}'

Чтобы передать шаблон поиска в качестве переменной:

var='<car>'
PATTERN="$var" awk -v n=3 '
  $0 ~ ENVIRON["PATTERN"] && ++n == 3 {getline; print; exit}'

Здесь использование ENVIRONвместо -vas -vрасширяет последовательности с обратной косой чертой и обратные косые черты часто встречаются в регулярных выражениях (поэтому их необходимо удваивать -v).

GNU awk4.2 или выше позволяет назначать переменные как строго типизированные регулярные выражения . Пока его режим POSIX не включен (например, через $POSIXLY_CORRECTпеременную окружения, вы можете сделать:

# GNU awk 4.2 or above only, when not in POSIX mode
gawk -v n=3 -v pattern="@/$var/" '
  $0 ~ pattern && ++n == 3 {getline; print; exit}'

Как передать шаблон поиска также в качестве переменной в приведенной выше команде
— WanderingMind

@ WanderingMind, см. Редактировать.
— Стефан Шазелас

4

Вот Perl один:

perl -ne 'print && exit if $c==3; $c++ if /<Car>/;' file 

С помощью GNU grepвы также можете анализировать вывод:

grep -A 1 -m 3 '<Car>' file | tail -n 1

От man grep:

-A NUM, --after-context=NUM
          Print NUM lines of trailing context after matching lines.  
          Places a line containing a group separator (--) between 
          contiguous  groups  of  matches.          
-m NUM, --max-count=NUM
          Stop reading a file after NUM matching lines.  


1

Вот еще один способ с sed:

sed -n '/<Car>/{x;/.\{2\}/{x;$!{n;p};q};s/.*/&./;x}' infile

Это использует место для подсчета.
Каждый раз, когда он встречает соответствующую <Car>ему строку, он xизменяет буферы и проверяет, есть ли в буфере удержания ровно N-1 вхождений символа. Если проверка прошла успешно, она xснова меняется, и если не в последней строке, она вытягивает nстроку ext и pнабирает пространство шаблона, а затем qиспользует. В противном случае он просто добавляет еще один .символ в область удержания, и e xменяется обратно.


0

Вот простое решение командной строки.

grep -F -A1 '<Car>' filename | grep -E -v '<Car>|--' | tail -n +3 |head -n +1

Если вы измените значение +3 после tail, вы можете указать любую n-ю строку.


Не уверен, почему вы добавили теги, sed, awk и т. Д. Если вы хотите решение, использующее конкретное приложение, утилиту, то вы должны указать это в вопросе или заголовке.
— BSD
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.