假设您有一个包含许多 xml 文档的文件,例如
<a>
<b>
...
</a>
in between xml documents there may be plain text log messages
<x>
...
</x>
...
我将如何过滤此文件以仅显示给定正则表达式与该 xml 文档的任何一行匹配的那些 xml 文档?我在这里谈论的是一个简单的文本匹配,因此正则表达式匹配部分也可能完全不了解底层格式 - xml。
你可以假设根元素的开始和结束标签总是在它们自己的行上(尽管可能会被空白填充),并且它们只用作根元素,即同名的标签不会出现在下面根元素。这应该可以完成工作,而不必求助于 xml 感知工具。
概括
我写了一个 Python 解决方案、一个 Bash 解决方案和一个 Awk 解决方案。所有脚本的想法都是一样的:逐行检查并使用标志变量来跟踪状态(即我们当前是否在 XML 子文档中以及我们是否找到了匹配的行)。
在 Python 脚本中,我将所有行读入一个列表,并跟踪当前 XML 子文档开始的列表索引,以便在到达结束标记时打印出当前子文档。我检查每一行的正则表达式模式,并使用一个标志来跟踪我们完成处理后是否输出当前子文档。
在 Bash 脚本中,我使用一个临时文件作为缓冲区来存储当前的 XML 子文档,并等待它完成写入,然后再使用
grep
它来检查它是否包含与给定正则表达式匹配的行。Awk 脚本类似于 Base 脚本,但我使用 Awk 数组作为缓冲区而不是文件。
测试数据文件
data.xml
我根据您问题中给出的示例数据,对照以下数据文件 ( ) 检查了这两个脚本:Python 解决方案
这是一个简单的 Python 脚本,可以满足您的要求:
以下是运行脚本以搜索字符串“stuff”的方式:
这是输出:
以下是您如何运行脚本来搜索字符串“øæå”:
这是输出:
您还可以指定
-v
或--invert-match
搜索不匹配的文档,并使用标准输入:重击解决方案
这是相同基本算法的 bash 实现。它使用标志来跟踪当前行是否属于 XML 文档,并使用临时文件作为缓冲区来存储正在处理的每个 XML 文档。
以下是运行脚本来搜索字符串“stuff”的方法:
这是相应的输出:
以下是您可以如何运行脚本来搜索字符串“øæå”:
这是相应的输出:
awk 解决方案
这是一个
awk
解决方案 - 虽然我awk
的不是很好,所以它很粗糙。它使用与 Bash 和 Python 脚本相同的基本思想。它将每个 XML 文档存储在一个缓冲区(一个awk
数组)中,并使用标志来跟踪状态。当它完成处理一个文档时,如果它包含与给定正则表达式匹配的任何行,它就会打印它。这是脚本:这是您的称呼:
这是相应的输出: