Mostra as linhas correspondentes a um padrão e as 4 linhas antes de cada

4

Por exemplo, deste arquivo:

CREATE SYNONYM I801XS07 FOR I8010.I801XT07
               *
ERROR at line 1:
ORA-00955: name is already used by an existing object


CREATE SYNONYM I801XS07 FOR I8010.I801XT07
               *
ERROR at line 1:
ORA-00955: name is already used by an existing object



Table altered.


Table altered.


Table altered.


Table altered.


Table altered.


Table altered.


Table altered.


Table altered.

DROP INDEX I8011I01
           *
ERROR at line 1:
ORA-01418: specified index does not exist



Index created.

Eu quero encontrar ORA- e mostrar a linha ORA- e as 4 linhas anteriores:

CREATE SYNONYM I801XS07 FOR I8010.I801XT07
               *
ERROR at line 1:
ORA-00955: name is already used by an existing object

CREATE SYNONYM I801XS07 FOR I8010.I801XT07
               *
ERROR at line 1:
ORA-00955: name is already used by an existing object

DROP INDEX I8011I01
           *
ERROR at line 1:
ORA-01418: specified index does not exist
    
por Javier Ortega 11.10.2011 / 16:40

3 respostas

4

Suponhamos que você esteja em um sistema antigo, como o HP-UX, que não tenha utilitários GNU, apenas o velho e original BSD ou AT & T "grep". Você poderia fazer algo assim:

#!/bin/sh

awk '/ORA-/ { print line1; print line2; print line3; print line4; print $0 }\
// {line1 = line2; line2 = line3; line3 = line4; line4 = $0}' $1

Sim, há muitas condições de borda que não acertam, mas o que você quer por nada? Além disso, como você está trabalhando em um sistema operacional e hardware antiquado e decodificado, provavelmente não tem a potência da CPU para lidar com erros.

    
por 11.10.2011 / 17:57
10

A opção -B para grep faz exatamente isso: grep -B 4 ORA- your_file .

Na ausência do GNU grep , eu adaptei o exemplo grep4 do tutorial grymoire sed :

#!/bin/sh

# grepB4: prints out 4 lines before and the line including pattern
# if there is only one argument, exit

case $# in 
    1);;
    *) echo "Usage: $0 pattern";exit;;
esac;

sed -n '
'/"$1"/' !{
    # does not match - add this line to the hold space
    H
    # bring it back into the pattern space
    x
    # Two lines would look like .*\n.*
    # Three lines look like .*\n.*\n.*
    # Delete extra lines - keep four
    s/^.*\n\(.*\n.*\n.*\n.*\)$//
    # put it back in hold space
    x
}
'/"$1"/' {
    # matches - append the current line
    H
    # bring hold space contents into pattern space
    g
    # print the 4 lines
    p
    # add the mark
    a\
---
}'

Uso: grepB4 pattern < file .

Bruce Ediger's answer faz essencialmente a mesma coisa com awk , que geralmente tem menos sintaxe enigmática que sed .

    
por 11.10.2011 / 16:47
1
awk 'NR == FNR && $0 ~ p {
  for (i = FNR; i >= FNR - l; i--)
    nr[i]; next
  }
FNR in nr  
BEGIN {
  ARGV[ARGC++] = ARGV[ARGC - 1]
  }' l=4 p=ORA- infile   

No Solaris, use nawk ou / usr / xpg4 / bin / awk .

    
por 13.10.2011 / 21:59