egrep в сценариях оболочки - PullRequest
4 голосов
/ 16 июня 2020

Кто-нибудь может помочь здесь. Если это невозможно с egrep, мы также будем очень признательны за другие предложения.

Я пытаюсь написать выражение egrep для grep ORA-00942 с «UTL_RECOMP_SLAVE_75», когда оно находится в следующей строке строки «UTL_RECOMP_SLAVE_75» . Однако ORA-00942 в любой другой строке файла следует игнорировать. ORA-00942 должен быть обработан только тогда, когда он находится в следующей строке, за которой следует "UTL_RECOMP_SLAVE_75".

ORA-12012: error on auto execute of job "SYS"."UTL_RECOMP_SLAVE_75"
ORA-00942:     <<<<<<<<<<<<<<<<<< should be grepped along with "UTL_RECOMP_SLAVE_75"

ORA-00490: error text is xyz
ORA-00942:   <<<<<<<<<<<<<<<< this should be ignored

Ответы [ 5 ]

2 голосов
/ 17 июня 2020

Вот простое решение с помощью grep.

grep -A1 UTL_RECOMP_SLAVE_75 inputfile | grep -B1 ORA-00942

Вы можете сделать это с помощью двух частей grep. Поскольку у grep есть удобные опции -An и -Bn.

например: grep UTL_RECOMP_SLAVE_75 -A3 inputfile

Распечатать 3 строки конечного контекста после сопоставления строк, а параметр -Bn: Распечатать n строк ведущий контекст перед совпадающими строками.
пожалуйста, прочтите в man grep.

В этом ответе я передал первый grep на второй. Но вы можете сделать это в два этапа также с tmp_file вместо pipe, чтобы увидеть, как работают команды grep.

grep -A1 UTL_RECOMP_SLAVE_75 inputfile >tmp_file
grep -B1 ORA-00942 tmp_file

И вы можете указать более точное соответствие, если оно вам нужно. например:

grep -A1 -w UTL_RECOMP_SLAVE_75 inputfile | grep -B1 -w ^ORA-00942
1 голос
/ 17 июня 2020

Это будет делать то, что вы хотите, используя любой awk в любой оболочке в каждом UNIX поле:

$ awk '/ORA-00942/ && (p ~ /UTL_RECOMP_SLAVE_75/){print p ORS $0} {p=$0}' file
ORA-12012: error on auto execute of job "SYS"."UTL_RECOMP_SLAVE_75"
ORA-00942:     <<<<<<<<<<<<<<<<<< should be grepped along with "UTL_RECOMP_SLAVE_75"
1 голос
/ 16 июня 2020

Использование sed:

sed -n '/"UTL_RECOMP_SLAVE_75"/{N;/\n.*ORA-00942/p;D}'
1 голос
/ 16 июня 2020

Вот решение Perl. Он не такой короткий, как ответ sed, но я считаю его более читаемым:

perl -nle 'print if (/^ORA-00942/ && $wanted); if (/UTL_RECOMP_SLAVE_75/) {$wanted=1} else {$wanted=0}' /your/file

Или немного более короткую версию:

perl -nle 'print if (/^ORA-00942/ && $wanted); $wanted=(/UTL_RECOMP_SLAVE_75/ ? 1 : 0)' /your/file

Это устанавливает флаг $wanted в значение true, если текущая строка содержит «UTL_RECOMP_SLAVE_75» или false, если это не так.

При этом печатаются только строки, начинающиеся с «ORA-00942», и только если $wanted истинно.

Если вы также хотите распечатать предыдущую строку, используйте вместо этого решение Эда Мортона , которое печатает оба.

0 голосов
/ 16 июня 2020

Я бы посоветовал комбинацию grep и awk:

Вы можете использовать grep -n, чтобы получить строки, содержащие «ORA-00942», вы получите что-то вроде:

2:line_2 contains ORA-00942
8:line_5 contains ORA-00942

Отсюда, используя awk с ':' в качестве разделителя полей, вы можете получить номера строк, которые содержат «ORA-00942» ([2,8]).

Вы можете затем используйте grep -n, чтобы упорядочить строки, содержащие «UTL_RECOMP_SLAVE_75», что может выглядеть примерно так:

4:line_4 contains UTL_RECOMP_SLAVE_75
7:line_7 contains UTL_RECOMP_SLAVE_75

Используя awk снова, вы получите номера строк, которые содержат «UTL_RECOMP_SLAVE_75» ([4,7]) .

Отсюда вы обрабатываете оба списка номеров строк, чтобы получить совпадающие.

Советы и хитрости : вместо сохранения строк, содержащих "UTL_RECOMP_SLAVE_75" , вы берете номера строк плюс один (вместо [4,7] у вас есть [5,8]), может оказаться проще найти два списка с одинаковыми номерами, чем проверять значения «плюс один».

...