使用 sed 从 XML 文件中获取特定文本

使用 sed 从 XML 文件中获取特定文本

不知道为什么我没有得到这个。我已经搜索和测试我的命令几个小时了,但一无所获。

正文是:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><result expand="changes,testResults,metadata,logEntries,plan,vcsRevisions,artifacts,comments,labels,jiraIssues" key="EP-ED-JOB1-174" state="Failed" lifeCycleState="Finished" number="174" ....

而且我只是想把那state="Failed" 部分拔出来,也有可能state="Successful"

我已经尝试过一百万种变体:

sed '/state=".*"/p' htmlResponse.txt

但括号、转义斜杠等似乎与整个文本块匹配。我的正则表达式有什么问题?

答案1

抛开强制性的“您确实应该使用适当的 XML 解析器,因为正则表达式不足以解析 XML”注释,我在您的sed行中看到了两个问题:

  1. ".*""将从第一个到最后一个匹配,因为.匹配"
  2. sed命令/.../p打印全线如果它与正则表达式匹配。

对于快速而肮脏的 HTML 抓取 shell 脚本,我建议执行以下两件事:

  1. 用于"[^"]*"匹配“引号、任意数量的非引号字符、结束引号”
  2. grep -o提取文件中与正则表达式匹配的部分要容易得多

所以这会让你的命令更像:

grep -o 'state="[^"]*"'

或者,如果你真的必须使用 sed:

sed -n 's/.*\(state="[^"]*"\).*/\1/p'

答案2

正确的方法是使用 XML 解析器,例如xmlstarlet

printf 'state="%s"\n' $(xmlstarlet sel -t -v "//result/@state" -n htmlResponse.txt)

输出:

state="Failed"

仅获取属性的值(从所有result节点,如果有多个):

xmlstarlet sel -t -v "//result/@state" -n htmlResponse.txt

答案3

您可能想要匹配整行并打印只是匹配组

sed -r 's/.*state="([^"]*)".*/\1/' htmlResponse.txt

这实际上只是拉出了Failedor Successful(不包括state=它前面的部分),我怀疑这就是你想要的。但如果您确实需要,您可以轻松地将其添加回来,或者使用稍微不同的正则表达式,正如伍德兹的回答一样

然而,作为桑迪普提到, 这是使用正则表达式解析 HTML(或 XML)根本不可靠。交互地使用grepsed搜索内容是一回事,但如果这是需要执行重要任务的脚本的一部分并实际工作,您应该正确解析 XML。

相关内容