如何在类似 XML 的文本文件中找到第 n 个包含单词的“

如何在类似 XML 的文本文件中找到第 n 个包含单词的“

我有一个类似 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 有时安装xmlstarletxml.

答案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 || '&#xa;')

相关内容