Использовать sed для печати с первой строки до строки, содержащей последнее вхождение шаблона?

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

sed -n '1,/<pattern>/p' <file> sed '/<pattern>/q' <file> 

Например, скажем, у меня есть файл, имеющий следующие строки:

 this is a cow this is a goat this is a some fish this is a fishie this is a fish this is a lion this is a cat 

Теперь выходы:

 $ sed '/fish/q' file this is a cow this is a goat this is a some fish $ sed -n '1,/fish/p' file this is a cow this is a goat this is a some fish 

Я хочу, чтобы результат начинался с самой первой строки до строки, содержащей последнее появление рыбы, т. Е. Мой желаемый результат:

 this is a cow this is a goat this is a some fish this is a fishie this is a fish 

Как это сделать с помощью sed ?

4 Solutions collect form web for “Использовать sed для печати с первой строки до строки, содержащей последнее вхождение шаблона?”

Попробуй это:

 $ tac infile | sed -n '/fish/,$p' |tac 

В общем случае, если вы запустите команду sed, вы получите всю строку от первого сопоставленного шаблона до конца входного файла.

 $ sed -n '/fish/,$p' file this is a some fish this is a fishie this is a fish this is a lion this is a cat 

Итак, мое решение: если мы запустим команду tac на входном файле, ваш последний сопоставленный шаблон изменится на первый шаблон. см. результат tac infile :

 $ tac infile this is a cat this is a lion this is a fish this is a fishie this is a some fish this is a goat this is a cow 

Команда tac такая же, как команда cat , тогда как tac печатает файлы в обратном порядке.

Теперь, если мы закончим первый sed comand, вы получите все строки первого совпадающего шаблона до конца входного файла. как:

 $ tac infile | sed -n '/fish/,$p' this is a fish this is a fishie this is a some fish this is a goat this is a cow 

Хорошо, закончил. Нам нужно снова запустить команду tac чтобы вернуть строки в исходный порядок:

 $ tac infile | sed -n '/fish/,$p' |tac this is a cow this is a goat this is a some fish this is a fishie this is a fish 

Готово!

Это довольно просто – требуется лишь небольшая координация между двумя буферами sed . Например:

 sed -n 'H;/fish/!d;$!n;x;p;G ' <<\INFILE this is a cow this is a goat this is a some fish this is a fishie this is a fish this is a lion this is a cat INFILE 

Эта команда добавляет каждую строку в H старое пространство после вставленного символа \n ewline. Любая линия, которая делает ! не соответствует /fish/ сразу же после этого выводится с выхода. Что оставляет нас только /fish/ линии. Таким образом, строка перезаписывается с помощью строки ввода n ext. Затем узор и h старые пространства меняются местами – мы все-таки сделали H старой чертой. Теперь пространство шаблона – это H старое пространство и наоборот. Таким образом, мы просто ping все, что было спасено от последнего раза /fish/ линии соответствует.

Это может быть только до последнего совпадения совпадений, потому что оно только p зависает, когда находит совпадение, и оно сохраняет промежуточные строки в промежутке времени. Тем не менее, он хранит только как можно меньше между совпадениями – каждый раз, когда буферы изменяются, они обновляются. Вот ваш вывод:

 this is a cow this is a goat this is a some fish this is a fishie this is a fish 

Большое спасибо don cristi за то, что он показал мне, что я иногда пропускал рыбу. Теперь он позволяет нажимать буфер на оба конца каждый раз, когда он обновляется, и каждый раз переписывать текущее пространство шаблона перед его удалением – в случае. Он будет работать с рыбой в первой строке или последней, а любая строка между ними находится как можно ближе.

Еще одна вещь, которую я делал, заключалась в том, чтобы вытащить строку n ext на последней строке – это большой sed no-no. Еще раз спасибо, что помогаю мне в этом.

Более обстоятельный пример:

 sed 'x;/./G;//!x;/fish/p;//s/.*//;x;d' 

Надеюсь, это еще несколько проблем, связанных с другим. Шаблоны / h старых пространств e x меняются каждый цикл – и это должно избегать получения лишних пустых строк в результате редактирования s/// ubstitution в конце команды. Таким образом, буферы заменяются, и если буфер удержания не пуст, текущая строка добавляется в этот буфер, следуя символу \n ewline, в котором дополнительные строки будут возникать иначе. Иначе буферы просто меняются назад, и h старое пространство остается пустым для текущего цикла. Насколько я могу судить, эта команда сохраняет все пустые строки и все остальное, но просто останавливает печать в последнем матче.

Некоторая сложность, с которой я столкнулся, обычно связана с h старым пространством – единственный способ эффективно использовать его – это отстать – отстать – цикл строк, чтобы сравнить старые строки со старыми. Обычно я предпочитаю цикл N;P;D Вы можете сделать это, используя что-то в этих строках, например …

 sed -ne :n -e '/fish/!N;//p;//!bn' 

Там sed непрерывно добавляет строку ввода N ext к пространству рисунка, а b возвращается к метке :n чтобы повторить попытку, если рыба не соответствует ни одной из линий, которые она заложила до сих пор. Это только указывает линии – или линейные последовательности – которые соответствуют fish перед тем, как сбросить содержимое в конце линейного цикла и начать заново с помощью нового буфера.

Я намеренно не тестирую последнюю строку здесь – если последняя строка соответствует ей, будет напечатана, else – и с -n это верно даже для GNU sed – цикл просто закончит файл всей своей последней строкой или нет ,

Вы также можете использовать awk, который может быть короче, чем Sed:

 awk ' /^fish/ { print $0 }' filename.txt 

Некоторые люди могут написать это:

 awk ' /^fish/ { print $1 $2 $3 $4 $5 }' filename.txt 

$n представляет столбец. Ярлык $0 представляет всю строку.

Вопрос не очень ясен, но после некоторых итераций редактирования я считаю, что вам следует использовать pcregrep для этой задачи. Например, если вход

 this is a cow this is a goat this is a some fish this is a fishie this is a fish this is a lion this is a cat this is a fisherman this is a dog 

и выход желания

 this is a cow this is a goat this is a some fish this is a fishie this is a fish 

тогда

 pcregrep -M '(.|\n)*fish.*(?=(.|\n)*fish.*)' 

будет выполнять эту работу.

  • Извлечь определенное значение из блоков данных
  • sed regex для группы захвата между разделителями
  • Однострочный шрифт для вставки новой строки текста (буквально регулярное выражение, а значит, и многих экранированных символов) в файле конфигурации перед определенной строкой?
  • Дата изменения «29 июля 2011 года» на «20110729»
  • извлекать символы before () с помощью grep
  • Debian sed: невозможно прочитать
  • Извлечение нескольких экземпляров текста между теми же двумя строками текста
  • Как искать слово, сохраненное в пространстве удержания с помощью sed?
  • Заменить первый столбец файла с помощью вывода команды
  • Как распечатать только первое совпадение из каждой строки?
  • Почему мне не нужно избегать класса символов в sed, но мне нужно избегать остальных?
  • Какие символы следует избегать при изменении файла с помощью sed?
  • Interesting Posts

    Повторно подключить соединение с обратной связью ssh

    Как узнать, какое имя ввести для запуска программы после установки с помощью yum / rpm?

    Я хочу создать сценарий, чтобы мне не приходилось вводить su и пароль каждый раз

    Sniffing машина VirtualBox за NAT

    glibc memory alloction: arenas и отладка

    Измените одиночные пустые строки, чтобы удвоить пустые строки, используя awk

    Удалите все пробелы после определенного слова

    Как заставить gedit открывать новое окно независимо от существующих окон gedit всякий раз, когда текстовый файл дважды щелкнут на рабочем столе Gnome Debian 8?

    Где будут настроены дополнительные IP-адреса, назначенные сетевому адаптеру для CentOS 4.4?

    Как распаковать, изменить, перестроить и установить SRPM

    Имеет ли gsettings интерфейс GUI?

    «Inotifywait» для просмотра нескольких каталогов одновременно

    Как узнать, работает ли sshd с ClientAliveInterval> 0?

    Yum, принудительно обновить зависимости

    Запуск программы и обеспечение ввода

    Linux и Unix - лучшая ОС в мире.