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

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

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

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

  • sed, конвертировать одиночную обратную косую черту в двойную обратную косую черту
  • Форматировать вывод на определенную длину строки
  • Sed - замена строк с помощью группировок
  • использование sed для замены шаблона с помощью хэш-значений
  • Как заменить определенный текст на соответствующий номер строки с помощью sed?
  • unix: заменить один полный столбец в одном файле одним значением из другого файла
  •  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 ?

  • Как эхо экранировать экранированную строку
  • Почему в этом простом случае не является седой жадный?
  • sed - применять изменения в нескольких файлах
  • Сценарий, который выводит среднюю строку из нескольких групп, из файла
  • awk хотят суммировать по часам и переменные
  • Улучшить команду 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.*)' 

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

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