検索文字列に基づいてログからxmlを抽出するgrepまたはawk

検索文字列に基づいてログからxmlを抽出するgrepまたはawk

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行の番号の間の内容を抽出したいと思います。以下を試しました。

  1. 検索パラメータを検索し、行番号を識別します。
  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

関連情報