任务:
我正在尝试使用外壳程序脚本从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 ...