理想情况下,我希望能够做到的是:
cat xhtml文件.xhtml|
getElementViaXPath--path='/html/head/title'|
sed-e的%(^<;title>;|<;/title>;$)%g'>;titleOfXHTMLPage.txt
这实际上只是对Yuzem答案的解释,但我觉得不应该对其他人做这么多编辑,评论不允许格式化,所以
rdom(){local IFS=\>;read-d\<;ec;}
让我们将其称为“read_dom”而不是“rdom”,将其隔开一点并使用更长的变量:
读取dom(){
本地IFS=\>;
读取-d\<;实体内容
}
它定义了一个名为read_dom的函数。第一行将IFS(输入字段分隔符)设置为该函数的本地,并将其更改为>。这意味着,当您读取数据而不是在空格、制表符或换行符上自动拆分时,它会在“>”上拆分。下一行表示从stdin读取输入,而不是在换行时停止,而是在看到“<;”时停止字符(去离子器标志的-d)。然后使用IFS拆分读取的内容,并将其分配给变量实体和内容。因此,采取以下措施:
<;标签>;价值</标签>;
对read\u dom的第一次调用获取一个空字符串(因为“<;”是第一个字符)。因为没有’>’字符,所以IFS将其拆分为”>’。Read然后为这两个变量分配一个空字符串。第二个调用获取字符串“tag>value”。然后由IFS将其拆分为两个字段“tag”和“value”。Read然后分配变量,如:ENTITY=tag和CONTENT=value。第三个调用获取字符串“/tag>”。被IFS拆分为两个字段“/tag”和“”。Read然后分配如下变量:ENTITY=/tag和CONTENT=。第四个调用将返回非零状态,因为我们已到达文件末尾
现在,他的while循环进行了一些清理,以符合上述要求:
读取dom时
;做
如果[$ENTITY=“title”];然后
echo$内容
出口
fi
完成<;xhtml文件.xhtml>;titleOfXHTMLPage.txt
第一行只是说,“当read_dom函数返回零状态时,执行以下操作。”第二行检查我们刚才看到的实体是否为“title”。下一行回显标记的内容。四条线出口。如果不是标题实体,则循环在第六行重复。我们将“xhtmlfile.xhtml”重定向到标准输入(用于read\u dom函数),并将标准输出重定向到“titleOfXHTMLPage.txt”(循环中前面的回音)
现在为input.xml提供以下内容(类似于在S3上列出一个bucket):
<;ListBucketResult xmlns=”http://s3.amazonaws.com/doc/2006-03-01/“>;
<;名称>;sth项目</名称>;
<;IsTruncated>;假</IsTruncated>;
<;内容>;
<;键>;苹果[email protected]</键>;
<;最后修改>;2011-07-25T22:23:04.000Z</最后修改>;
<;ETag>&;引用;0032a28286680abee71aed5d059c6a09&;引用</ETag>;
<;尺寸>;1785年</尺寸>;
<;StorageClass>;标准</StorageClass>;
</内容>;
</ListBucketResult>;
以及以下循环:
读取dom时
;做
echo“$ENTITY=>;$CONTENT”
完成<;input.xml
你应该得到:
=>;
ListBucketResult xmlns=”http://s3.amazonaws.com/doc/2006-03-01/“=>;
名称=>;某物项目
/名称=>;
IsTruncated=>;错误的
/IsTruncated=>;
内容=>;
键=>;苹果[email protected]
/键=>;
LastModified=>;2011-07-25T22:23:04.000Z
/LastModified=>;
ETag=>&;引用;0032a28286680abee71aed5d059c6a09&;引用;
/ETag=>;
大小=>;1785
/大小=>;
StorageClass=>;标准
/StorageClass=>;
/内容=>;
因此,如果我们编写了一个while循环,如Yuzem的循环:
读取dom时
;做
如果[$ENTITY=“Key”];然后
echo$内容
fi
完成<;input.xml
我们将得到S3存储桶中所有文件的列表
编辑
如果出于某种原因本地IFS=\>不适用于您,如果您对其进行全局设置,则应在函数末尾重置它,如:
读取dom(){
原始_IFS=$IFS
IFS=\>;
读取-d\<;实体内容
IFS=$ORIGINAL_IFS
}
否则,您稍后在脚本中执行的任何行分割都将出错
编辑2
要拆分属性名称/值对,可以扩充read\u dom()如下:
读取dom(){
本地IFS=\>;
读取-d\<;实体内容
本地ret=$?
TAG_NAME=${ENTITY%%*}
属性=${ENTITY}
返回$ret
}
然后编写函数解析并获取所需数据,如下所示:
解析dom(){
如果[$TAG_NAME=“foo”];则
评估本地$ATTRIBUTES
echo“foo大小为:$size”
elif[$TAG_NAME=“bar”];然后
评估本地$ATTRIBUTES
echo“条形图类型为:$type”
fi
}
然后,当您读取dom时,调用解析dom:
读取dom时
;做
解析dom
完成
然后给出以下标记示例:
<;示例>;
<;棒材尺寸=“棒材尺寸”类型=“金属”>;钢筋含量</酒吧>;
<;foo size=“1789”type=“未知”>;食品内容</foo>;
</示例>;
您应该获得以下输出:
$cat example.xml |/bash_xml.sh
棒材类型为:金属
福的尺寸是:1789
编辑3另一位用户说他们在FreeBSD中遇到问题,建议保存读取的退出状态,并在读取结束时返回,如:
读取dom(){
本地IFS=\>;
读取-d\<;实体内容
本地RET=$?
TAG_NAME=${ENTITY%%*}
属性=${ENTITY}
返回$RET
}
我看不出有什么理由不起作用