我有一个类似 XML 的文本文件,由于 XML 违规,无法使用 XML 解析器对其进行解析:
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
我只想剪切文件中n
打开的标签后的单词。<
该文件应采用 XML 语法,这意味着行可能会有所不同。
我的预期输出是,
1 - note
2 - to
3 - /to
4 - from
5 - /from
6 - heading
7 - /heading
8 - body
9 - /body
10 - /note
答案1
$ awk -F"[<>]" '{for(i=2;i<=NF;i+=2){print ++j" - "$i}}' input.xml
1 - note
2 - to
3 - /to
4 - from
5 - /from
6 - heading
7 - /heading
8 - body
9 - /body
10 - /note
答案2
注意:这个答案是在用户解释 XML 格式不正确之前写的。我将其留在这里,因为它可能对其他人有帮助。
XML小星 能够生成XML文档的元素结构:
$ xml el file.xml
note
note/to
note/from
note/heading
note/body
这与您的预期输出不同,但可能足以满足您想要实现的目标。
它还能够将 XML 转换为 PYX,在不同的行上显示开始和结束标记:
$ xml pyx file.xml
(note
-\n
(to
-Tove
)to
-\n
(from
-Jani
)from
-\n
(heading
-Reminder
)heading
-\n
(body
-Don't forget me this weekend!
)body
-\n
)note
由此,很容易得到您想要的输出:
$ xml pyx file.xml | sed -n -e 's/^(//p' -e 's/^)/\//p'| nl
1 note
2 to
3 /to
4 from
5 /from
6 heading
7 /heading
8 body
9 /body
10 /note
这些sed
说明将删除不以 或 开头的行(
,)
并根据您在问题中指定的方式替换这些字符。该nl
实用程序将行号放在行上。
XMLStarlet 有时安装xmlstarlet
为xml
.
答案3
grep
+awk
解决方案:
grep -Eo '<[^<>]+>' input.xml | awk '{ gsub(/[<>]/,""); printf "%-3s - %s\n", NR, $0 }'
输出:
1 - note
2 - to
3 - /to
4 - from
5 - /from
6 - heading
7 - /heading
8 - body
9 - /body
10 - /note
或者使用单个 GNUawk
命令:
awk -v FPAT='</?[^<>]+>' '{ for(i=1;i<=NF;i++) printf "%-3s - %s\n", ++c, $i }' input.xml
答案4
这是一个 XQuery 解决方案,以防您想要适用于任何 XML 的解决方案,甚至是包含注释、DTD、自关闭元素等的笨拙 XML。
declare function local:f($e) {
$e / (name(), local:f(*), ('/' || name()))
};
for $tag at $p in local:f(/*)
return ($p || ' - ' || $tag || '
')