Использовать 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 ?

  • Как манипулировать CSV-файлом с помощью sed или awk?
  • Как заменить символ || с | "" | использование sed
  • sed для печати шаблона, который охватывает линии
  • Переименуйте файлы (удалите некоторые символы, которые не всегда одинаковы)
  • Удалить столбец, который содержит конкретный текст
  • Заменить 1-й с 1), 2-й с 2), ... в GNU Sed
  • Объединяйте строки из разных файлов, если шаблон сопоставляется
  • Использование 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.*)' 

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

    Interesting Posts

    Как установить чип по умолчанию в alsamixer? Или отключить автоматическое отключение звука в PulseAudio?

    Сделать файл python доступным из любого места всеми пользователями

    Обеспечение безопасности NFS в многопользовательской среде

    Как сделать N-образный diff?

    Убивать другие процессы в трубопроводе (программно)

    установить ограничение подключения через iptables

    : () {: |: &} ;: Как эта бета-версия BASH работает подробно?

    Можно ли перечислить только определенные подкаталоги?

    Ошибка в lpr, но принтер не печатает

    Запустить терминал для входа в Debian

    в окне «Новый терминал»: количество от 1 до 10

    Удалите старые файлы, но сохраняйте их каждую неделю / месяц / год

    Как получить доступ к гостевой консоли KVM без пароля?

    что означает «Чтение заголовка Swap:« Успех »означает?

    Как я могу переместить файлы по типу рекурсивно из каталога и его подкаталогов в другой каталог?

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