XMLが書き込まれるログファイルがあります。すべてのノードに特定の文字列を持つすべてのXMLを検索して抽出する必要があります。
たとえば、ログファイルには検索パラメータを含む複数のXMLがあります。
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
予想される出力は、コンソールに印刷されるか、別々のファイルに書き込まれた2つのXMLです。
XML1:
<CreateDataABC>
<Tag1>searchparam</Tag1>
</CreateDataABC>
XML2:
<DataCreatedABC>
<TagA>otherparam</TagA>
<TagB>searchparam</TagB>
<TagC>otherparam</TagC>
</DataCreatedABC>
XML内の「searchparam」の位置は固定されておらず、唯一の定数は「ABC」文字列と「searchparam」です。
sedを使用して2行の番号の間の内容を抽出したいと思います。以下を試しました。
- 検索パラメータを検索し、行番号を識別します。
- ABCの次の発生を見つけて、番号を取得します。
特定の行で以前に発生したABCが見つからないようです。
前にこのようなことをした人はいますか?
編集:サンプルログ形式と予想される出力が更新されました。
答え1
この試み:
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
答え2
これは私が書いたものですが、これを行うより短くてエレガントな方法があると確信しています。
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