如何使用xmlint--xpath在每次匹配后追加换行符
我有以下HTML代码:如何使用xmlint--xpath在每次匹配后追加换行符,xml,shell,xpath,xmllint,Xml,Shell,Xpath,Xmllint,我有以下HTML代码: <textarea name="command" class="setting-input fixed-width" rows="9">1</textarea><textarea name="command" class="setting-input fixed-width" rows="5">2</textarea> 目前我正在使用: xmllint --xpath '//textarea[@name="comm
<textarea name="command" class="setting-input fixed-width" rows="9">1</textarea><textarea name="command" class="setting-input fixed-width" rows="5">2</textarea>
目前我正在使用:
xmllint --xpath '//textarea[@name="command"]/text()' --html
但它不会在每次比赛后添加换行符。我做了以下丑陋的把戏,请随时提供更好的解决方案 通过使用以下命令将
替换为\n
更改了HTML代码:
sed 's/\<\/textarea/\'$'\n\<\\/textarea/g' f
sed的/\您好,从2020年开始
从libxml的v2.9.9开始,这种行为就不再存在了
但是,如果您使用的是比这更早的版本,并且不想从源代码构建libxml只是为了获得固定的xmllint
,那么您将需要其他解决方法之一。例如,在撰写本文时,最新的CentOS 8仍在使用libxml(2.9.7)版本,其行为与OP描述的方式相同
正如我从中收集到的,从理论上讲,可以将命令馈送到older的--shell
选项中(/dev/null
在最末端抑制它(冒着抑制打印到标准错误的其他消息的风险)
解释了XMLStarlet选项(另请参见):
-fo格式化输出,期望HTML输入,并恢复尽可能多的错误输入fo-H-R
- 这将添加一个
根节点,使OP示例中的片段成为有效的XML
- 这将添加一个
-select节点基于xpathsel-T-T-v//xpath-n
//xpath
- 输出纯文本(
)而不是XML-T
- 使用给定的模板(
),该模板返回节点的值(-t
),而不是节点本身(允许您放弃在XPath表达式中使用-v
)text()
- 最后,添加一个换行符(
)-n
- 输出纯文本(
xmllint--shell
解决方案,因为它很糟糕。添加了一个实际使用OP数据的XMLStarlet示例。试试,它提供了两个选项:
:与旧的--xpath
相同,节点之间用--xpath
分隔\n
:与旧的--xpath0
相同,节点之间用--xpath
分隔\0
a.html
):
测试输出1:
1
2
测试命令2:
# xmllint --xpath0 '//textarea[@name="command"]/text()' --html a.html | xargs -0 -n1
测试输出2:
1
2
这是一个包装器脚本,完全用于新行分隔的输出(对于
xmllint
的旧版本):
!/bin/bash
#将脚本包装到
#-在Xpath查询上有换行符分隔的输出
#-在非常旧的版本上实现--xpath
/usr/bin/xmllint--xpath&>/dev/null
实现_xpath=$?
换行符\u分隔\u xmllint\u版本=20909
当前版本=$(xmllint--version |&awk'NR==1{print$NF;exit})
args=(“$@”)
如果[$@=*--xpath*];则
#迭代位置参数
对于((i=0;i=20909)| |$file==-| |$file==/dev/stdin | |$xpath==/| |$xpath==string\(*]]
然后
exec/usr/bin/xmllint“$@”
其他的
exec/usr/bin/xmllint“${args[@]}”-shell您现在是如何获得输出的?您在哪里测试的?@Babai假设上述HTML代码在文件f中可用,xmllint--xpath'//textarea[@name=“command”]/text()“--HTMLF
事实上,我在在线工具中测试过它,文本将出现一行新的内容..因此试图理解您要将其打印到哪里..@Babai在这种情况下,我猜您使用的工具的行为与xmllint
不同。您好,从未来开始!此行为在libxml2版本2.9.9和--xpath
中得到了修复(最后)在转储XPath节点时,是否符合您的期望。如果您使用的是旧的libxml2,请参阅下面使用XMLStarlet的替代解决方案。您可以使用其他字符作为sed的分隔符,例如,%
,因此不需要跳出斜杠。如果不美观,请不要发布它。“sed”不是一个XML解析器,拥有此功能将非常好乌尔merged@AdamSiemion不确定他们是否有访问gnome git repo的rw权限。如果他们在github上托管他们的源代码,我很乐意发送一个拉取请求。另外,需要他们团队中的人做一些健全性检查。@Cyker你的代码还在那里,仍然打开,但是你的--xpath
修复了为v2.9.9添加新行的问题。谢谢!@Theudea非常感谢您的提醒。这一更改以字符串形式硬编码\n
,这使得使用\0
进行分离几乎不可能。因此,此修补程序无法再合并,我不会重新设置基础。我将把它留在那里,以防有人不需要最新的功能,而是\0
@Cyker Bummer。非常感谢您的努力,不是吗ess.该链接指向了此页面上已接受的答案。哈。捕捉得好。我的剪贴板中一定有其他内容。现在已修复。:)
如果您正在解析其他人的HTML,还值得注意的是“格式良好”(X)如今,xmllint
和xmlstartet
可以无误解析的各种HTML似乎是……一种罕见的东西。你可以按照建议尝试xmllint--HTML
,这对输入格式来说稍微宽容一些。有时即使这样也不起作用,我会先把输入的HTML传递一次。或者放弃d使用正则表达式,此时我有两个问题。
# xmllint --xpath '//textarea[@name="command"]/text()' --html a.html
1
2
# xmllint --xpath0 '//textarea[@name="command"]/text()' --html a.html | xargs -0 -n1
1
2
#!/bin/bash
# wrapper script to
# - have newline delimited output on Xpath querys
# - implements --xpath on very old releases
/usr/bin/xmllint --xpath &>/dev/null
implements_xpath=$?
newlines_delimited_xmllint_version=20909
current_version=$(xmllint --version |& awk 'NR==1{print $NF;exit}')
args=( "$@" )
if [[ $@ == *--xpath* ]]; then
# iterate over positional parameters
for ((i=0; i<${#args}; i++)); do
if [[ ${args[i]} == --xpath ]]; then
xpath="${args[i+1]}"
unset args[i+1]
unset args[i]
break
fi
done
if [[ ($implements_xpath==0 && $current_version>=20909) || $file == - || $file == /dev/stdin || $xpath == / || $xpath == string\(* ]]
then
exec /usr/bin/xmllint "$@"
else
exec /usr/bin/xmllint "${args[@]}" --shell <<< "cat $xpath" | sed '1d;$d;s/^ ------- *$//;/^$/d'
fi
else
exec /usr/bin/xmllint "$@"
fi