![grep 或 awk 根据搜索字符串从日志中提取 xml](https://linux22.com/image/134084/grep%20%E6%88%96%20awk%20%E6%A0%B9%E6%8D%AE%E6%90%9C%E7%B4%A2%E5%AD%97%E7%AC%A6%E4%B8%B2%E4%BB%8E%E6%97%A5%E5%BF%97%E4%B8%AD%E6%8F%90%E5%8F%96%20xml.png)
我有一个日志文件,其中记录了 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 来提取两个行号之间的内容,我尝试了以下操作:
- 搜索搜索参数并识别行号。
- 找到 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