grep 或 awk 根据搜索字符串从日志中提取 xml

grep 或 awk 根据搜索字符串从日志中提取 xml

我有一个日志文件,其中记录了 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

预期输出是在控制台上打印或写入单独文件的两个 XML。

XML1:

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

XML2:

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

XML 中“searchparam”的位置永远不会固定,唯一的常量是“ABC”字符串和“searchparam”。

我想使用 sed 来提取两个行号之间的内容,我尝试了以下操作:

  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

相关内容