在 xml 文件中,我正在搜索刺“
有更好的方法吗?
find /opt/mortagage/application.xml -type f -exec egrep -ri "<file:write" /dev/null {} + |uniq| sed '/<!--.*-->/d' | sed '/<!--/,/-->/d'
/opt/mortagage/application.xml: <file:write doc:id="16630" path="${file.location}" doc:name="Save file to directory">
/opt/mortagage/application.xml: <file:write doc:name="Write to complete folder" doc:id="18890" path='#["${file.completeLocation}" ++ vars.zipFileName]' config-ref="File_Config_completed">
/opt/mortagage/application.xml: <file:write doc:name="Write to complete folder" doc:id="19990" Path='#["${file.completeLocation}" ++ vars.zipFileName]' config-ref="File_Config_completed">
“更好的方法”是对结构化数据使用专用处理器,在这种情况下,命令行 XML 处理器可以轻松完成。
使用kislyuk/yq:
xq -r '.. | ."file:write"? | arrays[] // . | ."@path", ."@Path" | strings' in.xml
使用mikefarah/yq(完全忽略命名空间):
yq -oy '.. | .write? | select(kind == "map") // .[] | ."+@path" // ."+@Path"' in.xml
使用xmlstarlet:
xmlstarlet sel -t -m '//file:write' -v '@path' -v '@Path' -n in.xml
使用 libxml/xmllint:
xmllint
需要声明实际的命名空间(您在示例中未提供),或者通过诉诸 local-name()
检查xmllint
也不支持多场比赛的string(…)
功能,所以它最多只能输出像 path="${file.location}"
这样的全属性节点。解决方法可能是随后使用其他工具(如 awk
或 sed
)来修剪它们。xmllint --xpath '//*[local-name()="write"]/@path | //*[local-name()="write"]/@Path' \
in.xml | sed 's/^.*\?="\|"$//g' # removes all up to the first =" and a final "
它们都输出类似:
${file.location}
#["${file.completeLocation}" ++ vars.zipFileName]
#["${file.completeLocation}" ++ vars.zipFileName]