grep ou awk para extrair o xml do log com base na string de pesquisa

0

Eu tenho um arquivo de log que tem XMLs sendo registrados. Eu preciso pesquisar e extrair todos os XMLs que possuem uma string específica em qualquer um dos nós.

por exemplo. o arquivo de log terá vários xml's contendo o parâmetro de pesquisa.

randomlogentry1
randomlogentry2
Printing XML:<CreateDataABC>
    <Tag1>searchparam</Tag1>
</CreateDataABC>
randomlogentry3
randomlogentry4
randomlogentry5
Printing XML: <DataCreatedABC>
       <TagA>otherparam</TagA>
       <TagB>searchparam</TagB>
       <TagC>otherparam</TagC>
    </DataCreatedABC>
randomlogentry6
randomlogentry7

A saída esperada são os dois XML impressos no console ou gravados em arquivos separados.

XML1:

<CreateDataABC>
     <Tag1>searchparam</Tag1>
</CreateDataABC>

XML2:

<DataCreatedABC>
     <TagA>otherparam</TagA>
     <TagB>searchparam</TagB>
     <TagC>otherparam</TagC>
</DataCreatedABC>

A posição de 'searchparam' em um XML nunca é fixa e as únicas constantes são a string 'ABC' e o 'searchparam'.

Eu pensei em usar o sed para extrair entre dois números de linha para os quais tentei o seguinte:

  1. Pesquise pelo searchparam e identifique o nº da linha
  2. Encontre a próxima ocorrência de ABC e obtenha o número da linha,

De alguma forma eu não consigo encontrar a ocorrência anterior de ABC a partir de uma linha específica !!

Alguém já fez isso antes?

EDIT: Atualizado o formato de log de exemplo e a saída esperada.

    
por Saravanakumar Mohan 25.05.2018 / 10:18

2 respostas

0

Tente isto:

Max='grep -c "^Printing" file.xml'

for count in 'seq 1 $Max'
do
    sed -nr '/Printing/H;//,/ABC/G;s/\n(\n[^\n]*){'$count'}$//p'  file.xml | sed 's/Printing XML://' > $count.xml
done
    
por 25.05.2018 / 10:35
0

Aqui está o que eu escrevi, mas tenho certeza que existe uma maneira mais curta e mais elegante de fazer isso.

searchstring=searchparam
filename=test.log
pattern1=ABC

linenums=($(grep -n "${searchstring}" ${filename} | awk -F":" '{print $1}'))
len=${#linenums[@]}

for (( i=0; i<${len}; i++ ));
do
  currentline=${linenums[$i]}
  relativeendlinearray=($(tail -n +${currentline} ${filename} | grep -n "${pattern1}" | awk -F":" '{print $1}'))
  actualendline=$(($currentline+${relativeendlinearray[0]}-1))

  index=$currentline
  while [ $index -ne 0 ]
        do
        found='sed "${index}q;d" ${filename} | grep "${pattern1}"'
        if [ -n "$found" ]; then
            actualstartline=$index
            break;
        fi
        index=$[$index-1]
  done

  if [ -n "$found" ]; then
        echo ""
  else
        echo "Log break detected, content across multiple files"
  fi

  echo "Start Line" ${actualstartline}
  echo "Current Line" ${currentline}
  echo "End Line" ${actualendline}
  sed -n "${actualstartline},${actualendline}p" ${filename}
done
    
por 29.05.2018 / 13:44

Tags