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

8

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

<Car>
10456
</Car>
<Car>
70192
</Car>
<Car>
4598
</Car>
DJ180
источник
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.  
Тердон
источник
3

С GNU awkвами можно сделать:

gawk -v RS='</Car>' 'NR==3 && $0=$2' inputFile
Джайпал Сингх
источник
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меняется обратно.

don_crissti
источник
0

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

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

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

BSD
источник
Не уверен, почему вы добавили теги, sed, awk и т. Д. Если вы хотите решение, использующее конкретное приложение, утилиту, то вы должны указать это в вопросе или заголовке.
BSD