【问题标题】:How to grep multiple strings with -A如何使用 -A grep 多个字符串
【发布时间】:2012-07-12 15:23:51
【问题描述】:

我需要对 XML 文件中包含的数据进行 grep。我需要获取多个元素,最后一个在节点内。我正在研究的元素之间有一堆数据。我可以轻松地 grep 像这样的多个元素:

grep -E "<first|<second|<third|<seventh" file.xml

但由于我的文件结构如下所示:

<first>First</first>
<second>Second</second>
<third>Third</third>
<fourth>Fourth</fourth>
<fifth>Fifth</fifth>
<sixth flexible="true">
    <low>0.09</low>
    <high>5.90</high>
</sixth>
<seventh flexible="false">
    <low>1.82</low>
    <high>3.14</high>
</seventh>

我没有得到&lt;seventh&gt; 节点内的数字数据(没想到用那个命令)。所以我尝试使用grep -An(之后)开关,其中“n”是初始匹配后要匹配的行数,以获得第七个节点的其余部分:

grep -E "<first" -E "<second" -E "<third" -E -A3 "<seventh" file.xml

哪个会返回:

<first>First</first>
<second>Second</second>
<third>Third</third>
<seventh flexible="false">
    <low>1.82</low>
    <high>3.14</high>
</seventh>

然后我可以对其进行按摩以获得最终结果(实际上只需要来自第七个节点的“高”数据及其相关的第一个、第二个和第三个字符串)。但是,这不起作用,我在 &lt;first 之后立即获取前三个元素,它忽略了命令的其余部分。

我也试过了:

grep -E "<first|<second|<third" -E -A3 "<seventh" file.xml

这给了我类似的结果,但完全忽略了命令的“-E -A3 "&lt;seventh”部分。好吧,我想不会忽略,因为 -A3 仍在向后应用到命令的前面部分。我知道您可以使用命令后开关,但您可以控制它们的回退距离吗?

我阅读了有关 grep 的手册页,但没有看到如何将命令链接在一起。如果这很重要,我使用的是 Mac,但如果需要,我可以轻松访问 Linux 和 Windows 机器。

我怎样才能得到我想要的数据?

【问题讨论】:

    标签: xml unix grep


    【解决方案1】:

    首先,请再次查看man grep,发现不需要多个-Egrep 也不需要多个模式。

    其次,如果您知道您需要seventh 的上下文而不是其他人,只需使用两个命令:

    $ grep -E '<first|<second|<third' file.xml; grep -A3 '<seventh' file.xml
    <first>First</first>
    <second>Second</second>
    <third>Third</third>
    <seventh flexible="false">
        <low>1.82</low>
        <high>3.14</high>
    </seventh>
    

    如果你真的不知道,那么最好使用xpath 或其他 xml 解析工具。

    另见this question

    【讨论】:

    • 感谢您的帮助,但您的解决方案无法为我提供我正在寻找的数据。您和迈克尔对 xpath 的建议看起来是解决问题的好方法。事实上,我做了一个蛮力的 grep & sed 脚本来让数据进入一个可管理的状态。像这样的东西:grep -E -A3 "&lt;first|&lt;second|&lt;third|&lt;seventh" file.xml | sed -e 's/&lt;fourth.*fourth&gt;//' -e 's/&lt;fifth.*fifth&gt;//' -e 's/&lt;sixth.*sixth&gt;//' -e 's/^[ \t]*//' -e '/^.*$/s' 因为我在每个搜索词之后得到了 3 行,所以我得到了太多的数据并使用 sed 来清理它。这工作正常,所以我可以继续。
    【解决方案2】:

    不要使用正则表达式来搜索 XML。它们不是为这项工作而设计的。您的代码将是错误的。例如,如果某些字符串出现在 cmets 或 CDATA 部分中,或者输入包含名为 &lt;firstly&gt; 的元素,或者换行符的排列方式不同,@Levitsky 给出的代码将失败。 (有时代码错误并不重要,因为只有 99% 的时间可以工作,但如果这是你的要求,我希望你能这么说。)

    搜索 XML 的方法是使用 XPath,或者对于更精细的搜索,使用 XQuery。

    满足您需求的 XPath 解决方案非常简单。假设您提供的 XML 在 wrapper 元素内,则 XPath 2.0 表达式为 wrapper/(first, second, third, seventh)。所以这个任务的 XPath 不仅更可靠,而且更容易。

    【讨论】:

    • 感谢您的帮助。 Xpath 非常可行,但由于我没有使用 XML 解析器,因此我使用的 XML 示例与真正的 XML 相比过于简化。我昨天用它做了实验,并从真正的 XML 中得到了结果,但我只能得到序列化的数据(EG 所有 节点数据,然后是所有 节点数据等),而不是关联数据:code &lt;first&gt;First&lt;/first&gt; &lt;second&gt;Second&lt;/second&gt; &lt;third&gt;Third&lt;/third&gt; &lt;seventh flexible="false"&gt; &lt;low&gt;1.82&lt;/low&gt; &lt;high&gt;3.14&lt;/high&gt; &lt;/seventh&gt; 使用逗号给了我一个“无效令牌:”令牌错误。
    猜你喜欢
    • 1970-01-01
    • 2015-05-24
    • 2015-02-15
    • 2014-12-21
    • 2013-04-19
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 2015-12-04
    相关资源
    最近更新 更多