理想情况下,我希望能够做到以下几点:
cat xhtmlfile.xhtml |
getElementViaXPath --path='/html/head/title' |
sed -e 's%(^<title>|</title>$)%%g' > titleOfXHTMLPage.txt
好的,您可以使用xpath实用程序。我猜perl的XML :: Xpath包含它。
lxml
解析的 Python 脚本——它将文件名或 URL 作为第一个参数,XPath 表达式作为第二个参数,并打印与给定表达式匹配的字符串/节点。
#!/usr/bin/env python
import sys
from lxml import etree
tree = etree.parse(sys.argv[1])
xpath_expression = sys.argv[2]
# a hack allowing to access the
# default namespace (if defined) via the 'p:' prefix
# E.g. given a default namespaces such as 'xmlns="http://maven.apache.org/POM/4.0.0"'
# an XPath of '//p:module' will return all the 'module' nodes
ns = tree.getroot().nsmap
if ns.keys() and None in ns:
ns['p'] = ns.pop(None)
# end of hack
for e in tree.xpath(xpath_expression, namespaces=ns):
if isinstance(e, str):
print(e)
else:
print(e.text and e.text.strip() or etree.tostring(e, pretty_print=True))
lxml
可以通过pip install lxml
进行安装。在Ubuntu上,您可以使用sudo apt install python-lxml
。
python xpath.py myfile.xml "//mynode"
lxml
也接受 URL 作为输入:
python xpath.py http://www.feedforall.com/sample.xml "//link"
注意: 如果您的XML具有没有前缀的默认命名空间(例如
xmlns=http://abc...
),则您必须在表达式中使用p
前缀(由“hack”提供),例如//p:module
从pom.xml
文件获取模块。如果p
前缀已在您的XML中映射,则需要修改脚本以使用另一个前缀。
这是一个一次性脚本,仅用于从apache maven文件中提取模块名称。请注意,节点名称(module
)带有默认命名空间{http://maven.apache.org/POM/4.0.0}
的前缀:
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modules>
<module>cherries</module>
<module>bananas</module>
<module>pears</module>
</modules>
</project>
module_extractor.py:
from lxml import etree
for _, e in etree.iterparse(open("pom.xml"), tag="{http://maven.apache.org/POM/4.0.0}module"):
print(e.text)
pip install
来替代 apt-get
或 yum
命令。谢谢! - E. Moffat例如:我的智能家居程序运行我们的家庭。在此过程中,它会读取大量不同格式的数据,我无法控制。我从不使用专门的、适当的工具,因为我不想花费超过几分钟的时间来阅读我需要的数据。通过FS和RS调整,这个awk解决方案对于任何文本格式都可以完美地工作。但是,当您的主要任务是在该格式中处理大量数据时,这可能不是正确的答案!
我昨天遇到了从bash解析XML的问题。以下是我为任何分层数据格式执行的操作。作为奖励——我直接将数据分配给bash脚本中的变量。
为了让事情更容易阅读,我将分几个阶段介绍解决方案。从OP测试数据中,我创建了一个文件:test.xml
在bash中解析XML并提取其中的数据,每行限制在90个字符:
awk 'BEGIN { FS="<|>"; RS="\n" }; /host|username|password|dbname/ { print $2, $4 }' test.xml
我通常使用更易读的版本,因为在实际生活中我经常需要进行不同的测试,这样更容易进行修改:
awk 'BEGIN { FS="<|>"; RS="\n" }; { if ($0 ~ /host|username|password|dbname/) print $2,$4}' test.xml
awk 'BEGIN { FS="<|>"; RS="\n" }; { if ($0 ~ /host|username|password|dbname/) print $2"=\""$4"\"" }' test.xml
eval $( awk 'BEGIN { FS="<|>"; RS="\n" }; { if ($0 ~ /host|username|password|dbname/) print $2"=\""$4"\"" }' test.xml ); echo "host: $host, username: $username, password: $password dbname: $dbname"
$(rm -rf ~)
的密码执行 eval
命令(如果您将注入的引号从双引号更改为单引号,则可以使用 $(rm -rf ~)'$(rm -rf ~)'
来避免)。 - Charles Duffy'"'"'
的结构替换数据中的任何字面单引号。 - Charles Duffyeval "$(...)"
而不仅仅是eval $(...)
。如果你想知道为什么后者会导致错误的结果,请尝试运行以下命令:cmd=$'printf \'%s\\n\' \'first * line\''
,然后比较eval $cmd
和eval "$cmd"
的输出结果。如果没有引号,那么在eval
开始解析之前,你的*
将被替换为当前目录中的文件列表(这意味着这些文件名本身将作为代码进行评估,从而打开更多的安全问题)。 - Charles Duffy$3
变量中(MacOS,z-shell终端)。 - ElectroBuddha<
和>
符号的顺序来改进,如下所示:rdom () { local IFS=\> ; read -d \< E C ;}
变成:
rdom () { local IFS=\< ; read -d \> C E ;}
while
循环结束时输出另一个XML文件,这可能会成为问题。试试 xpe。它是专门为此目的构建的。您可以使用 python3 pip 安装它:
pip3 install xpe
你可以这样使用它:
curl example.com | xpe '//title'
上述命令返回:
示例域名
如果你想要 XML 属性,这个方法是可行的:
$ cat alfa.xml
<video server="asdf.com" stream="H264_400.mp4" cdn="limelight"/>
$ sed 's.[^ ]*..;s./>..' alfa.xml > alfa.sh
$ . ./alfa.sh
$ echo "$stream"
H264_400.mp4
Example
的命令是:echo '<html><head><title>Example</title></body></html>' | yq -p xml '.html.head.title'
。参见链接:yq,一些例子。 - jpsengecho '<html><head><title>Example</title></body></html>' | yq -p xml '.html.head.title'
输出Example
。参见:yq,一些示例 - undefined