Использование ОС OPEN STEP 4.2 ... В настоящее время я использую следующую sed
команду:
sed -n '1,/141.299.99.1/p' TESTFILE | tail -3
Эта команда найдет один экземпляр в файле с IP-адресом 141.299.99.1 и также включит в себя 3 строки перед ним, что все хорошо, за исключением того, что я также хотел бы найти все экземпляры IP и 3 строки перед ним и не только первый.
Ответы:
Вот попытка эмулировать
grep -B3
с помощью движущегося окна sed, основанного на этом примере GNU sed (но, надеюсь, POSIX-совместимого - с подтверждением @ StéphaneChazelas):Первые два выражения заполняют многострочный буфер шаблонов и позволяют ему обрабатывать граничный случай, в котором перед первым соответствием имеется менее 3 строк предыдущего контекста. Среднее выражение (совпадение с регулярным выражением) выводит строку за верхнюю часть окна до тех пор, пока нужный текст совпадения не будет смещен в буфер шаблонов. Финал
$!N;D
прокручивает окно на одну строку, кроме случаев, когда оно достигает конца ввода.источник
-e
не является специфичным для GNU. Чтобы быть POSIX / портативным, вам это нужно, так как после этого ничего не может быть}
(и вам нужно;
до него).-e '1h;2,4{H;g;}' -e '1,3d'
? У меня нет системы без GNU для тестирования (и--posix
переключатель GNU sed , похоже, не заботится).sed
помощью набора инструментов из семейной реликвии, который является потомком традиционного Unix sed. Спецификация POSIX / Unix дляsed
находится по адресу pubs.opengroup.org/onlinepubs/9699919799/utilities/sed.htmlgrep
сделает лучшую работу из этого:В
-B 3
средства для печати три строки перед каждым матчем. Это будет печатать--
между каждой группой строк. Чтобы отключить это, используйте--no-group-separator
также.-B
Опция поддерживается GNUgrep
и большинство версий BSD , а также ( OSX , FreeBSD , OpenBSD , NetBSD ), но это технически не является стандартным вариантом.источник
С
sed
вами можно сделать раздвижное окно.Это делает это. Но будьте осторожны -
bash
безумное поведение расширяется,!
даже когда цитируется !!! в командной строке из вашей истории команд может сделать его немного сумасшедшим. Добавьте к команде префикс,set +H;
если вы обнаружите, что это так. Чтобы затем включить его (но почему ???) сделатьset -H
потом.Это, конечно, будет применяться только тогда , когда вы были с помощью
bash
- хотя я не верю , что ты. Я вполне уверен, что вы работаете сcsh
- (это, случается, оболочка, чье безумное поведениеbash
подражает расширению истории, но, возможно, не до крайностей, которые приняла оболочка c) . Так , вероятно\!
, должен работать. Я надеюсь.Это весь переносимый код: POSIX описывает свои три оператора следующим образом: (хотя стоит отметить, что я только подтвердил, что это описание существовало еще в 2001 году)
Итак, в первой строке вы добавляете дополнительную строку в пространство шаблонов, чтобы она выглядела так:
Затем в первой строке и в каждой последующей строке, за исключением самой последней, вы добавляете еще одну строку в пространство шаблона. Так это выглядит так:
Если ваш ip-адрес найден внутри вас,
P
наберите до первой новой строки, поэтому просто введите строку 1 здесь. В конце каждого цикла выD
выбираете одно и то же и начинаете заново с того, что осталось. Итак, следующий цикл выглядит так:...и так далее. Если ваш ip будет найден на любом из этих трех, самый старый распечатает - каждый раз. Так ты всегда впереди всего на три строчки.
Вот быстрый пример. Я получу трехстрочный буфер для каждого числа, оканчивающегося на ноль:
Это немного сложнее, чем ваш случай, потому что я должен был чередовать либо
0\n
новой строки или0$
конца шаблонного пространства, чтобы более близко походить на вашу проблему - но они немного отличаются тем, что для этого требуется привязка - что может быть немного сложным, поскольку шаблон-пространство постоянно смещается.Я использовал нечетные случаи 10 и 52, чтобы показать, что, пока якорь является гибким, то и вывод тоже. Полностью переносимый, я могу достичь тех же результатов, вместо этого рассчитывая на алгоритм и делаю:
И расширить поиск при ограничении моего окна - с 0 до 9 и 0 и с 3 строк до двух.
В любом случае, вы поняли идею.
источник
sed '...' $filename
, Между прочим - я оставил периоды из вашей собственной строки поиска, но на самом деле это не периоды в шаблоне - они представляют какой-либо один символ. Вам, вероятно,oct\.oct\.oct\.oct
следует избегать их, чтобы они соответствовали только периодам.Поскольку вы упомянули, что у вас нет
-B
опцииgrep
, вы можете использовать Perl (например), чтобы сделать скользящее окно из 4 строк:Ответ Рамеша делает то же самое с
awk
.источник
Когда доступно, вы можете использовать pcregrep :
источник
Вы можете реализовать тот же базовый подход, что и другие ответы, не связанные с grep, в самой оболочке (это предполагает относительно недавнюю оболочку, которая поддерживает
=~
):В качестве альтернативы, вы можете записать весь файл в массив:
источник
Если ваша система не поддерживает
grep
контекст, вы можете вместо этого попробовать ack-grep :ack
такой инструмент, как grep, оптимизированный для программистов.источник
perl
, вы можете использоватьack
.В этом
awk
решении используется массив, который всегда будет содержать 3 строки перед текущим шаблоном. Следовательно, когда шаблон сопоставляется, содержимое массива вместе с текущим шаблоном печатается.тестирование
После того, как я выполню команду, вывод
источник
В большинстве из них
/141.299.99.1/
также будут совпадать (например)141a299q99+1
или141029969951
потому, что.
в регулярном выражении может быть представлен любой символ.Использование
/141[.]299[.]99[.]1/
безопаснее, и вы можете добавить дополнительный контекст в начале и в конце всего регулярного выражения , чтобы убедиться , что он не соответствует3141.
,.12
,.104
и т.д.источник