sed: возврат последнего совпадения вхождения до конца файла
используя sed, как вернуть последнее совпадение до конца файла? (FYI это было упрощено)
до сих пор я пробовал:
sed -n '/ Statistics |/,$p' logfile.log
который возвращает все строки с первого матча (почти весь файл)
Я тоже пробовал:
$linenum=`tail -400 logfile.log | grep -n " Statistics |" | tail -1 | cut -d: -f1`
sed "$linenum,$!d" logfile.log
это работает, но не будет работать над ssh-соединением в одной команде, действительно нужно, чтобы все это было в одном конвейере.
формат файла журнала: следует:
(есть заголовки статистики с данными sub, записанными в файл журнала каждую минуту, цель этой команды-вернуть самый последний заголовок статистики вместе с любыми связанными ошибками, которые возникают после заголовка)
Statistics |
Stuff
More Stuff
Even more Stuff
Statistics |
Stuff
More Stuff
Error: incorrect value
Statistics |
Stuff
More Stuff
Even more Stuff
Statistics |
Stuff
Error: error type one
Error: error type two
EOF
возврат должен быть:
Statistics |
Stuff
Error: error type one
Error: error type two
6 ответов
ваш пример скрипта имеет пробел перед статистикой, но ваши примеры данных, похоже, нет. Это имеет регулярное выражение, которое предполагает, что статистика находится в начале строки; настроить, если это неверно.
sed -n '/^Statistics |/h;/^Statistics |/!H;$!b;x;p'
когда вы видите статистику, замените пространство удержания текущей строкой (h
). В противном случае добавьте в пространство удержания (H
). Если мы не находимся в конце файла, остановитесь здесь (b
). В конце файла распечатайте пространство удержания (x
извлечь содержимое трюм; p
печать).
на sed
script, команды необязательно имеют префикс "address". Чаще всего это регулярное выражение, но оно также может быть номером строки. Адрес /^Statistics |/
выбирает все строки, соответствующие регулярному выражению; /^Statistics |/!
выбирает строки, не соответствующие регулярному выражению; и $!
соответствует всем строкам, кроме последней строки в файле. Команды без явного адреса выполняются для всех входных строк.
редактировать объяснить напишите более подробно и добавьте следующее.
обратите внимание, что если вам нужно передать это на удаленный хост, используя ssh
, вам понадобятся дополнительные уровни цитирования. Одним из возможных обходных путей, если он становится слишком сложным, является сохранение этого сценария на удаленном хосте и просто ssh remotehost path/to/script
. Другим возможным обходным путем является изменение выражений адресации, чтобы они не содержали восклицательных знаков (это проблематично в командной строке, например, в Бить.)
sed -n '/^Statistics |/{h;b};H;${x;p}'
это тоже несколько проще!
третьим возможным обходным путем, если stdin вашего SSH-конвейера не привязан к другим вещам,является передача скрипта с вашего локального хоста.
echo '/^Statistics |/h;/^Statistics |/!H;$!b;x;p' |
ssh remotehost sed -n -f - file
Это может сработать для вас:
sed '/Statistics/h;//!H;$!d;x' file
Statistics |
Stuff
Error: error type one
Error: error type two
Если вы довольны awk
решение, это своего рода работает (помимо получения дополнительной пустой строки):
awk '/^Statistics/ { buf = "" } { buf = buf "\n" } END { print buf }' input.txt
sed ':a;N;$!ba;s/.*Statistics/Statistics/g' INPUTFILE
должен работать (GNU sed 4.2.1).
Он читает весь файл в одну строку, затем заменяет все, от начала до последнего Statistics
(слова в комплекте) с Statistics
, и печатает то, что осталось.
HTH
Это также может работать, немного более простая версия решения sed, данного другими выше:
sed -n 'H; /^Statistics |/h; ${g;p;}' logfile.log
выход:
Statistics |
Stuff
Error: error type one
Error: error type two