任务:

我正在尝试使用外壳程序脚本从xml标记中获取属性值,将其拆分并将其保存在.csv文件中。

这是xml的样子:

...

...

...

...

...

我想从"名称"属性中获取值并将其拆分,如下所示:

Type;Name;Port

我想要的输出csv文件应如下所示:

Type1;Name1;Port1

Type2;Name2;Port2

Type3;Name3;Port3

...

Typex;Namex;Portx

问题:

我无法在服务器上安装任何东西

我只能使用" ksh-awk" /" xmllint wihtout --xpath" /"标准linux命令"

我可以使用我想要的任何外壳语言。我更喜欢bash和ksh。

我的问题:

您认为有可能解决我的任务吗?

子任务的最佳方法是什么? (阅读,拆分,写作)

编辑:

服务器名称的示例数据:

T-TTT_AAA-A-SSS-PPPP

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

是的,xmllint --shell和awk或sed的混合应该是可能的。 Type1和Name1之间的分隔符是什么? 大写?

您能否显示一个使用真实数据(或形式与实际数据相似的数据)的示例? 这对于awk部分很重要

@Aserre ..完成..

因此,如果您具有T-TTT_AAA-A-SSS-PPPP,则输出应为T-TTT;AAA-A-SSS;PPPP,对吗?

没有xmllint,您可以解析输入

...

...

...

sed -n '/

作品。 请参见已接受的答案,以得到输出量完全相同的较小陈述。

这是我仅使用常用工具xmllint和sed想到的:

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

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

分解:

echo 'cat //host/servers/server/@name':我们将此命令传递给xmllint。它将捕获...内部所有节点的name属性

xmllint --shell data.xml:遍历data.xml并执行在交互式shell中作为参数传递的命令。

sed -n 's: name=\"\([A-Z][a-z0-9]*\)\([A-Z][a-z0-9]*\)-\(.*\)\":\1;\2;\3: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\}\)":\1,\2,\3:p'

这将匹配格式T-TTT_AAA-A-SSS-PPPP,类型和服务器名称具有任意长度。如果这不是您所需要的,请尝试绕开正则表达式或在regex标记中询问另一个问题。

这对我有用。 谢谢。 但是,如果还有另一个带有"名称"属性的标签,输出是否会被伪造?

不,它将专门在标记内查找" name"属性

但是语句的任何部分都没有:sed -n s: name="\(.*\)_\(.*\)-\(.\{4\}\)":\1,\2,\3:p表示它必须位于标记内。

是的,但这没关系,因为它是在xmllint提取数据之后执行的。 因此,只有在xmllint从标记中提取了name值之后,sed才会执行正则表达式

xidel -e '//server/@name' f.xml |  sed ...

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐