Как игнорировать все строки перед совпадением в bash?

Я бы проигнорировал все строки, которые встречаются перед совпадением в bash (также игнорируя совпадающую строку. Пример ввода может быть

R1-01.sql
R1-02.sql
R1-03.sql
R1-04.sql
R2-01.sql 
R2-02.sql
R2-03.sql

и если я сопоставляю R2-01.sql в этом уже отсортированном входе, я хотел бы получить

R2-02.sql
R2-03.sql

Ответы

Ответ 1

Много способов. Например: если ваш вход находится в list.txt

PATTERN="R2-01.sql"
sed "0,/$PATTERN/d" <list.txt

потому что 0,/pattern/ работает только на GNU sed (например, не работает на OS X), вот подделка решения.;)

PATTERN="R2-01.sql"
(echo "dummy-line-to-the-start" ; cat - ) < list.txt | sed "1,/$PATTERN/d"

Это добавит одну пустую строку в начало, поэтому реальный шаблон должен быть в строке 1 или выше, поэтому 1,/pattern/ будет работать - удаление всего из строки 1 (фиктивный) до шаблона.

Или вы можете печатать строки после шаблона и удалять 1-й, например:

sed -n '/pattern/,$p' < list.txt | sed '1d'

с awk, например:

awk '/pattern/,0{if (!/pattern/)print}' < list.txt

или мой любимый используйте следующую команду perl:

perl -ne 'print unless 1../pattern/' < list.txt

удаляет строку 1., когда шаблон находится на первой строке...

другое решение - обратное-удаление-обратное

tail -r < list.txt | sed '/pattern/,$d' | tail -r

если у вас есть команда tac, используйте вместо tail -r. Интересная вещь, чем /pattern/,$d' works on the last line but the 1,/pattern/d` не на первом.

Ответ 2

Как игнорировать все строки перед совпадением в bash?

Заголовок вопроса и ваш пример не совсем совпадают.

Распечатайте все строки из "R2-01.sql" в sed:

sed -n '/R2-01.sql/,$p' input_file.txt

Где:

  • -n подавляет печать пространства шаблонов в stdout
  • / запускает и завершает шаблон, соответствующий (регулярное выражение)
  • , отделяет начало диапазона от конца
  • $ обращается к последней строке ввода
  • p перекликается с пространством шаблонов в этом диапазоне до stdout
  • input_file.txt - это входной файл

Распечатайте все строки после "R2-01.sql" в sed:

sed '1,/R2-01.sql/d' input_file.txt
  • 1 обращается к первой строке ввода
  • , отделяет начало диапазона от конца
  • / запускает и завершает шаблон, соответствующий (регулярное выражение)
  • $ обращается к последней строке ввода
  • d удаляет пространство шаблонов в этом диапазоне
  • input_file.txt - это входной файл
  • Все, что не удалено, отражается на stdout.

Ответ 3

awk -v pattern=R2-01.sql '
  print_it {print} 
  $0 ~ pattern {print_it = 1}
'

Ответ 4

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

$ grep -A99999 $match $file

Очевидно, вам нужно выбрать значение для -A, которое будет достаточно большим, чтобы соответствовать всему содержимому; если вы используете слишком маленькое значение, вывод будет отключен без пауз.

Чтобы обеспечить получение всех результатов, вы можете сделать:

$ grep -A$(cat $file | wc -l) $match $file

Конечно, в этот момент вам может быть лучше с решениями sed, так как они не требуют двух чтений файла.

И если вам не нужна соответствующая строка, вы можете просто передать эту команду в tail -n+1 в пропустить первую строку вывода.

Ответ 5

вы можете сделать это, но я думаю, что jomo666 ответ был лучше.

sed -nr '/R2-01.sql/,${/R2-01/d;p}' <<END
    R1-01.sql
    R1-02.sql
    R1-03.sql
    R1-04.sql
    R2-01.sql
    R2-02.sql
    R2-03.sql
    END

Ответ 6

Perl - это еще один вариант:

perl -ne 'if ($f){print} elsif (/R2-01\.sql/){$f++}' sql

Чтобы передать в regex как аргумент, используйте -s, чтобы включить простой парсер аргументов

perl -sne 'if ($f){print} elsif (/$r/){$f++}' -- -r=R2-01\\.sql file