使用 shell 脚本从 xml 标签获取属性值并转换为 csv

Get attribute value from xml tags with shell script and convert to csv

任务:

我正在尝试使用 shell 脚本从 xml 标签获取属性值,将值拆分并保存在 .csv 文件中。

这是 xml 的样子:

<host>
  <servers>
    <server name="Type1Name1-Port1" >...</server>
    <server name="Type2Name2-Port2" >...</server>
    <server name="Type3Name3-Port3" >...</server>
    ...
    <server name="TypexNamex-Portx" >...</server>
  </servers>
</host>

我想从 "name" 属性中获取值并将它们拆分如下:
Type;Name;Port

我想要的输出 csv 文件应该是这样的:

Type1;Name1;Port1
Type2;Name2;Port2
Type3;Name3;Port3
...
Typex;Namex;Portx

问题:

我可以使用任何我想使用的 shell 语言。我更喜欢 bash 和 ksh.

我的问题:

编辑:

服务器名称的示例数据:

T-TTT_AAA-A-SSS-PPPP

其中 T 表示类型,A 表示应用程序名称,S 表示服务器名称,P 表示端口。 T、A和S的长度是可变的。 P 是常数。

这是我想出的,只使用常用工具:xmllintsed

echo 'cat //host/servers/server/@name' | xmllint --shell data.xml | sed -n 's: name=\"\([A-Z][a-z0-9]*\)\([A-Z][a-z0-9]*\)-\(.*\)\":,,:p'

sed 部分是根据发布时 OP 的示例完成的。

细分:

  • echo 'cat //host/servers/server/@name' :我们将此命令传递给 xmllint。它将捕获 <host><servers><server ...> ... </server></servers></hosts>
  • 内所有节点的 name 属性
  • xmllint --shell data.xml :遍历 data.xml 并执行在交互式 shell.
  • 中作为参数传递的命令
  • sed -n 's: name=\"\([A-Z][a-z0-9]*\)\([A-Z][a-z0-9]*\)-\(.*\)\":;;:p' :我们处理 xmllint 的输出以仅保留我们感兴趣的数据
    • xmllint 将产生以下输出:name="Type1Name1-Port1"
    • 我们定义了 3 个捕获组:一个大写字母后跟除大写以外的任何字符(Type),另一个大写字母后跟除大写以外的任何字符(Name),以及任何字符在 -" 字符之间
    • 我们告诉 sed 只打印匹配的字符串,用分号分隔

输出:

Type1;Name1;Port1
Type2;Name2;Port2
Type3;Name3;Port3
Typex;Namex;Portx

编辑:

为了适应您在评论中指出的模式,您只需更改 sed 正则表达式,例如:

sed -n 's: name=\"\(.*\)_\(.*\)-\(.\{4\}\)\":,,:p'

这将匹配格式 T-TTT_AAA-A-SSS-PPPP,类型和服务器名称的长度不限。尝试围绕正则表达式 fiddle 或在 regex 标签中提出另一个问题,如果这不是您所需要的。

如果没有 xmllint,您可以像这样解析输入

<host>
  <servers>
    <server name="Type1_Name1-Port1" >...</server>
    <server name="Type-2_Name2-Port2" >...</server>
    <server name="Type3_Name-3-Port3" >...</server>
  </servers>
</host>

sed -n '/<server name=/ s/[^"]*"\([^_]*\)_\([^"]*\)-\([^"]*\)".*/;;/p' inputfile
xidel -e '//server/@name' f.xml |  sed ...