Я ищу, чтобы отобразить строку 4598 в следующем файле. По сути, я хочу отобразить строку ПОСЛЕ n-го вхождения совпадения. В этом случае строка после 3-го появления <Car>. Как мне это сделать?
<Car>
10456
</Car>
<Car>
70192
</Car>
<Car>
4598
</Car>
Я ищу, чтобы отобразить строку 4598 в следующем файле. По сути, я хочу отобразить строку ПОСЛЕ n-го вхождения совпадения. В этом случае строка после 3-го появления <Car>. Как мне это сделать?
<Car>
10456
</Car>
<Car>
70192
</Car>
<Car>
4598
</Car>
Ответы:
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}'
Вот 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.
С GNU awkвами можно сделать:
gawk -v RS='</Car>' 'NR==3 && $0=$2' inputFile
Вот еще один способ с sed:
sed -n '/<Car>/{x;/.\{2\}/{x;$!{n;p};q};s/.*/&./;x}' infile
Это использует место для подсчета.
Каждый раз, когда он встречает соответствующую <Car>ему строку, он xизменяет буферы и проверяет, есть ли в буфере удержания ровно N-1 вхождений символа. Если проверка прошла успешно, она xснова меняется, и если не в последней строке, она вытягивает nстроку ext и pнабирает пространство шаблона, а затем qиспользует. В противном случае он просто добавляет еще один .символ в область удержания, и e xменяется обратно.
Вот простое решение командной строки.
grep -F -A1 '<Car>' filename | grep -E -v '<Car>|--' | tail -n +3 |head -n +1
Если вы измените значение +3 после tail, вы можете указать любую n-ю строку.
sed,awkили дажеgrep, желательно использовать синтаксический анализатор XML.