第一次出现XML元素时grep for pattern

问题描述 投票:0回答:3

我有一个多次出现XML元素的文件。我想只在第一个元素中grep一个模式。我想使用grep,因为我需要使用它作为if检查bash脚本的条件。请注意,遗憾的是,我无法保证XML元素包含在封闭标记中(此文件由我无法控制的其他程序生成)。

匹配“芒果”的例子

 <element>
       apple
       banana
       orange
       mango
 </element>
 <element>
       apple
       banana
       orange
       mango
 </element>

“mango”不匹配的示例

在以下XML片段中,我希望我的搜索失败b / c mango在第一个元素中不存在。

 <element>
       apple
       banana
       orange
 </element>
 <element>
       apple
       banana
       orange
       mango
 </element>
bash sed grep
3个回答
1
投票

这是我解决这个问题的方法,但我不得不使用grepsed相结合的管道。这个解决方案只对我有用,因为第一个<element>位于文件的第一行。

sed -n '0,/<\/element>/p' /path/to/file | grep -q mango

  1. 使用sed打印文件的第一行,直到element的第一个结束标记。
  2. 如果匹配grep,则使用mango退出true或false。

0
投票

对于XML数据的处理,我总是会推荐使用XML工具。只有那些工具才能以保存的方式处理XML的细节。对于命令行,可以使用名为xsltproc的工具。这是一个简单易用的XSLT处理器,它可以比sed更好地完成工作。唯一的缺点是你需要一个额外的xslt样式表。

样式表示例:test.xslt

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="1.0">
        <xsl:output method="text"/>

    <xsl:template match="element[position()=1]">
        <xsl:value-of select="."/>
        </xsl:template>

   <xsl:template match="*|@*|text()|comment()|processing-instruction()">
         <xsl:apply-templates select="*|@*|text()|comment()|processing-instruction()"/>
   </xsl:template>
</xsl:stylesheet>

使用stylesheet和xsltproc,您可以执行这样的命令

xsltproc test.xslt test.xml | grep mango

0
投票

这可能是一个很长的解决方案,但它的工作原理。

./check.sh mango

这为每个文件调用一个简单的awk脚本,由FILES变量引用

注意: 我保存的xml文件为:xml1xml2

对于上面的示例,它会生成以下输出: mango found in xml1 mango not found in xml2

是-here.awk:

BEGIN {
  tagOpened="not yet"
  tagsPresent=0
}

/<[[:alnum:]]+>/ {
  if (tagsPresent <= 1)   # remove this condition to check ALL occurencies
  {
    tagOpened="true"
    tagsPresent++
  }
}

/<[/][[:alnum:]]+>/ {
  tagOpened="false"
}

// {
  if (match($1, value) && tagOpened=="true" && length($1)==length(value))
  {
    found++
  }
}

END {

  if (found == tagsPresent)
  {
    print "present"
  }
  else
  {
    print "not"
  }
}

check.是

#! /bin/bash

function check()
{
  local file=$1
  local pattern=$2
  local result=$(cat $file | gawk -f is-here.awk -v value=$pattern)
  echo $result
}

FILES="xml1 xml2"

for file in $FILES
do
  result=$(check $file $1)

  if [ "$result" == "present" ]
  then
    echo "$1 found in $file"
  else
    echo "$1 not found in $file"
  fi  
done
© www.soinside.com 2019 - 2024. All rights reserved.