不知道为什么我没有得到这个。我已经搜索和测试我的命令几个小时了,但一无所获。
正文是:
<?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
行中看到了两个问题:
".*"
"
将从第一个到最后一个匹配,因为.
匹配"
- 该
sed
命令/.../p
打印全线如果它与正则表达式匹配。
对于快速而肮脏的 HTML 抓取 shell 脚本,我建议执行以下两件事:
- 用于
"[^"]*"
匹配“引号、任意数量的非引号字符、结束引号” 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
这实际上只是拉出了Failed
or Successful
(不包括state=
它前面的部分),我怀疑这就是你想要的。但如果您确实需要,您可以轻松地将其添加回来,或者使用稍微不同的正则表达式,正如伍德兹的回答一样。
然而,作为桑迪普提到, 这是使用正则表达式解析 HTML(或 XML)根本不可靠。交互地使用grep
或sed
搜索内容是一回事,但如果这是需要执行重要任务的脚本的一部分并实际工作,您应该正确解析 XML。