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
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:
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.
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
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