Как найти последнее вхождение шаблона и распечатать все строки после последнего появления [дубликат]

Я нашел способ осуществить то, что мы искали. Спасибо go @jc__ за подсказку с grubenv, а также @Anthon.

Вот мое решение: Поместите двоичный файл ядра iPXE (.lkrn) с настраиваемым сценарием для связи с сервером управления загрузкой в ​​/ boot

Затем настройте Grub

1- для использования переменной from grubenv

GRUB_DEFAULT=saved

2- Последовательная загрузка iPXE при загрузке из Grub и включение следующей команды перед загрузкой iPXE

set saved_entry='<menuentry to boot from local drive>'
save_env saved_entry

3- Добавьте пункт меню Grub, который загружает ОС с локального диска, с помощью

set saved_entry='<menuentry iPXE>'
save_env saved_entry

4- Если ничего не нужно done сервер управления загрузкой дает команду iPXE загрузиться с локального диска с помощью

sanboot --no-describe --drive 0x80

5 - Grub загружается снова и загружается на локальный диск, снова настраивая iPXE для следующей загрузки.

Время загрузки Windows 10, включая запрос сервера управления загрузкой, составляет около 25 секунд. Так что на самом деле довольно быстро. :)

5
09.09.2018, 14:37
5 ответов

На основе дубликата SO:

$ sed -n '/====/h;//!H;$!d;x;//p' sample.txt 
====

3rd run of script

End of 3rd script

Output of the command should look like below.

3rd run of script

End of 3rd script

Я начал писать объяснение, но на самом деле я не понимаю некоторые команды, поэтому просто сошлюсь на info sed.

4
27.01.2020, 20:34

Метод программных инструментов, более эффективный для больших файлов, поскольку он считывает только конец файла, а затем останавливается, когда находит последнее совпадение:

tac sample.txt | grep -F -m1 -B 999999 '====' | head -n -1 | tac

Примечание. :увеличьте или уменьшите 999999по мере необходимости, чтобы оно было длиннее любого возможного совпадения. Этот код будет работать лучше всего, если заранее известно, что последнее совпадение находится ближе к концу большого файла. См. также ответGlenn Jackman с вариантами awkи sed, которые позволяют избежать необходимости 999999. Для систем с очень низкими ресурсами grepболее эффективен, чем awkили sed.

Чтобы избежать угадывания, некоторые дополнительные statуродства сработали бы:

f=sample.txt; tac "$f" | grep -F -m1 -B $(stat -c '%s' "$f") '====' |
head -n -1 | tac
5
27.01.2020, 20:34

сохраните текст в file.txtи выполните эту команду:

awk 'p; /====/ $p' file.txt | tail -3

выход:

3rd run of script

End of 3rd script
1
27.01.2020, 20:34

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

с помощью GNU sed

tac file | sed '/====/Q' | tac

или awk

tac file | awk '/====/ {exit} 1' | tac

Идея двойного tacсостоит в том, чтобы инвертировать вопрос :Как напечатать все строки , предшествующиепервомувхождению шаблона. Это гораздо более простая проблема.

5
27.01.2020, 20:34

В awkпримерно так:

awk '/====/ { t = ""; next } { t = t $0 "\n"; } END { printf "%s", t; }' < sample.txt

Он сохраняет входные строки в tи очищает t, когда видит ====. Все, что там есть, напечатано в конце.

Обратите внимание, что

  • Строго говоря, ====не обязательно должно быть на отдельной строке (, вы не говорили, что это должно быть ). Если вы хотите распознавать его только тогда, когда он единственный в строке, используйте вместо этого /^====$/.
  • Это печатает весь ввод, если ====не виден. Для проверки наличия хотя бы одного необходимо дополнительное условие, см. ниже.
  • В вашем образце вывода отсутствует первая пустая строка после ====, но это может быть просто форматирование сообщения. Если вы хотите удалить его, добавьте канал в sed 1d.

Другая версия, которая начинает сохранять входные данные только после того, как виден разделитель ====, эффективно создавая пустой вывод, если ввод не содержит разделителя:

awk '/====/ { any = 1; t = ""; next } any { t = t $0 "\n"; } END { printf "%s", t; }' < sample.txt
1
27.01.2020, 20:34

Теги

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