我有一个多次出现XML元素的文件。我想只在第一个元素中grep一个模式。我想使用grep
,因为我需要使用它作为if
检查bash脚本的条件。请注意,遗憾的是,我无法保证XML元素包含在封闭标记中(此文件由我无法控制的其他程序生成)。
<element>
apple
banana
orange
mango
</element>
<element>
apple
banana
orange
mango
</element>
在以下XML片段中,我希望我的搜索失败b / c mango
在第一个元素中不存在。
<element>
apple
banana
orange
</element>
<element>
apple
banana
orange
mango
</element>
这是我解决这个问题的方法,但我不得不使用grep
和sed
相结合的管道。这个解决方案只对我有用,因为第一个<element>
位于文件的第一行。
sed -n '0,/<\/element>/p' /path/to/file | grep -q mango
sed
打印文件的第一行,直到element
的第一个结束标记。grep
,则使用mango
退出true或false。对于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
这可能是一个很长的解决方案,但它的工作原理。
./check.sh mango
这为每个文件调用一个简单的awk脚本,由FILES变量引用
注意:
我保存的xml文件为:xml1
,xml2
对于上面的示例,它会生成以下输出:
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