Как извлечь слова после некоторого шаблона в Linux? [Дубликат]

Мне кажется, вы пытаетесь сопоставить теги без «/» в конце. Попробуйте следующее:

<([a-zA-Z][a-zA-Z0-9]*)[^>]*(?<!/)>
44
задан codeforester 27 February 2017 в 07:09
поделиться

7 ответов

Это строка после , которая соответствует тому, что вам интересно, не так ли? В sed это можно сделать так:

sed -n '/ABC/{n;p}' infile

В качестве альтернативы вариант grep's A может быть тем, что вы ищете.

-A NUM, Print NUM lines of trailing context after matching lines.

Например, учитывая следующее входной файл:

foo
bar
baz
bash
bongo

Вы можете использовать следующее:

$ grep -A 1 "bar" file
bar
baz
$ sed -n '/bar/{n;p}' file
baz

Надеюсь, что это поможет.

29
ответ дан chooban 15 August 2018 в 17:44
поделиться
  • 1
    Примечание: {n;p}, похоже, поддерживается GNU sed, но не BSD sed. (Спасибо за команду chooban. Я очень уважаю awk и использовал его, но я стараюсь избегать переучивания своего барочного языка, когда это возможно. (Когда мне нужно awk, я использую perl). – Mars 1 April 2015 в 16:18
  • 2
    Коррекция: у меня был успех с BSD sed, добавив ;: sed -n /bar/{n;p;}. Работает с GNU sed. – Mars 1 April 2015 в 16:34
  • 3
    С оригинальным sed вам пришлось бы писать sed -n '/bar/{;n;p;}', потому что { и } были проанализированы точно так же, как и буквенные команды. – zwol 16 January 2016 в 05:05

Никогда не используйте слово «шаблон», поскольку оно очень неоднозначно. Всегда используйте «string» или «regexp» (или в шаблоне «globbing» оболочки), в зависимости от того, что вы действительно имеете в виду.

Конкретный ответ, который вы хотите:

awk 'f{print;f=0} /regexp/{f=1}' file

или специализируется на более общем решении N-й записи после regexp (ниже идиомы «c»):

awk 'c&&!--c; /regexp/{c=1}' file

Следующие идиомы описывают, как выбрать диапазон записей, заданных для определенного регулярного выражения:

a) Распечатайте все записи из некоторого regexp:

awk '/regexp/{f=1}f' file

b) Распечатайте все записи после некоторого регулярного выражения:

awk 'f;/regexp/{f=1}' file

c) Распечатайте N-ю запись после некоторого regexp:

awk 'c&&!--c;/regexp/{c=N}' file

d) Распечатайте каждую запись, кроме N-й записи, после некоторого регулярного выражения:

awk 'c&&!--c{next}/regexp/{c=N}1' file

e) Распечатайте N записей после некоторого регулярного выражения:

awk 'c&&c--;/regexp/{c=N}' file

f) Распечатайте каждую запись, кроме N записей, после некоторого регулярного выражения:

awk 'c&&c--{next}/regexp/{c=N}1' file

g) Распечатайте N записей из некоторого регулярного выражения:

awk '/regexp/{c=N}c&&c--' file

Я изменил имя переменной с «f» на «found» на «c» для «count», если это необходимо, так как это более выразительно, что переменная на самом деле IS.

105
ответ дан Ed Morton 15 August 2018 в 17:44
поделиться
  • 1
    не могли бы вы объяснить, что делает c&&!--c? Благодаря! – zack 15 February 2016 в 09:40
  • 2
    Если c отличен от нуля, уменьшите его и проверьте, если он равен нулю. Поэтому, если c началось с некоторого положительного числа, соответствующее действие будет выполнено после подсчета с этого числа до нуля. «Если с отличен от нуля», part является защитой, чтобы убедиться, что c не продолжает идти в отрицательные числа и потенциально снова обертывается на положительный, если входной файл массивный. – Ed Morton 15 February 2016 в 14:38

Мне нужно было напечатать ВСЕ строки после шаблона (ok Ed, REGEX), поэтому я остановился на этом:

sed -n '/pattern/,$p' # prints all lines after ( and including ) the pattern

Но так как я хотел напечатать все строки AFTER (и исключить pattern)

sed -n '/pattern/,$p' | tail -n+2  # all lines after first occurrence of pattern

Я полагаю, что в вашем случае вы можете добавить head -1 в конец

sed -n '/pattern/,$p' | tail -n+2 | head -1 # prints line after pattern
3
ответ дан Mark 15 August 2018 в 17:44
поделиться
  • 1
    Для вашего второго случая существует строгий способ: sed '0,/regex/d' – tlwhitec 12 August 2016 в 16:44

Если соответствие шаблону, скопируйте следующую строку в буфер шаблона, удалите возврат, а затем выйдите из-за побочного эффекта.

sed '/pattern/ { N; s/.*\n//; q }; d'
0
ответ дан Michael Back 15 August 2018 в 17:44
поделиться
  • 1
    q никоим образом не является расширением GNU. Это стандартная команда sed. – tripleee 16 January 2016 в 13:53
  • 2
    Yup * tripleee "... UR right ... – Michael Back 20 January 2016 в 20:08

Это может сработать для вас (GNU sed):

sed -n ':a;/regexp/{n;h;p;x;ba}' file

Использовать seds grep-like option -n, и если текущая строка содержит требуемое regexp, замените текущую строку следующим, скопируйте эту строку в пространство удержания (HS), распечатать линию, поменять пространство шаблона (PS) для HS и повторить.

0
ответ дан potong 15 August 2018 в 17:44
поделиться

awk Версия:

awk '/regexp/ { getline; print $0; }' filetosearch
2
ответ дан tue 15 August 2018 в 17:44
поделиться
  • 1
    Благодаря! Я забыл о опции -A в grep; он отлично работает с параметром +1 (строка с совпадающим рисунком не печатается). – user1537723 28 July 2013 в 21:36
  • 2
    Это будет происходить не так загадочно, когда вы этого меньше всего ожидаете, и в будущем это будет сложно. Перед тем, как решить getline, убедитесь, что вы готовы и полностью понимаете awk.info/?tip/getline . – Ed Morton 29 July 2013 в 00:29
  • 3
    Сделайте это awk.freeshell.org/AllAboutGetline – Ed Morton 4 August 2017 в 17:45

На самом деле sed -n '/pattern/{n;p}' filename выйдет из строя, если pattern соответствует continuous линиям:

$ seq 15 |sed -n '/1/{n;p}'
2
11
13
15

Ожидаемые ответы должны быть:

2
11
12
13
14
15

Мое решение:

$ sed -n -r 'x;/_/{x;p;x};x;/pattern/!s/.*//;/pattern/s/.*/_/;h' filename

Например:

$ seq 15 |sed -n -r 'x;/_/{x;p;x};x;/1/!s/.*//;/1/s/.*/_/;h'
2
11
12
13
14
15

Объясняет:

  1. x;: в начале каждой строки из ввода используйте x для обмена содержимым в pattern space & amp; hold space.
  2. /_/{x;p;x};: если pattern space, который фактически является hold space, содержит _ (это только indicator, указывающий, соответствует ли последняя строка pattern или not), затем используйте x для обмена фактическим содержимым current line на pattern space, используйте p для печати current line и x для восстановления этой операции.
  3. x: восстановить содержимое в pattern space и hold space.
  4. /pattern/!s/.*//: если current line НЕ соответствует pattern, это означает, что мы НЕ должны напечатайте следующую строку ниже, затем используйте команду s/.*//, чтобы удалить все содержимое в pattern space.
  5. /pattern/s/.*/_/: если current line соответствует pattern, это означает, что мы должны напечатать следующую строку ниже , тогда нам нужно установить indicator, чтобы сообщить sed распечатать строку NEXT, поэтому используйте s/.*/_/, чтобы заменить все содержимое в pattern space на _ (вторая команда будет использовать его, чтобы судить, если последняя строка соответствует pattern или нет).
  6. h: перезаписать hold space с содержимым в pattern space; то содержание в hold space равно ^_$, что означает, что current line соответствует pattern или ^$, что означает, что current line НЕ соответствует pattern.
  7. пятый шаг и шестой шаг не могут быть обменены, потому что после s/.*/_/, pattern space НЕ МОЖЕТ соответствовать /pattern/, поэтому s/.*// ДОЛЖЕН быть выполнен!
1
ответ дан Weike 15 August 2018 в 17:44
поделиться
  • 1
    Спасибо за хорошее объяснение, ++ ve – RavinderSingh13 6 June 2017 в 08:35
Другие вопросы по тегам:

Похожие вопросы: