我有一个尺寸不大的 XML 文件。我已经获得了这些信息,我所需要做的就是提取 XML 标记之间的一些值。因为XML
我的机器上没有可用的解析器实用程序。我正在寻找替代方法。
首先,有一个<capacity> </capacity
重复的 XML 标签 >nXML 文件中的时间数以及此 XML 标记之间还有许多其他不同的标记。
我必须<capacity> </capacity>
分别获取每个出现的 XML 标记,然后对其进行解析并提取它们下的值。
<subcolumns><capacity><name>45.90</name>
<index>0</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>
<capacity><name>57.09</name>
<index>1</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>
<capacity><name>55</name>
<index>2</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>
</subcolumns>
因此,我认为的逻辑是找到第一次出现的<capacity> </capacity>
XML 标记并将其打印到临时文件,然后删除第一次出现的位置。
<capacity><name>45.90</name>
<index>0</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>
此后,当第二次执行此操作时,<capacity> </capacity>
将考虑新的 XML 标记对。所以这必须重复多次,直到<capacity> </capacity>
找到最后一个标签。每次提取这部分数据都会发生变化并且可以提取。
<capacity> </capacity>
现在我想要的只是从主 XML 文件中选择第一次出现的XML 标记并将其打印到临时文件并删除该部分。
这就是我尝试过的,但没有任何效果。
sed -n '2,${/<capacity>\(.*\)<\/capacity>/\1/p;q;}' "<input XML file>" >> temp.txt
我进一步的想法是获取该临时文件进行处理并提取标签下所需的值capacity
。我已经为此编写了逻辑并且运行良好。
答案1
使用 XML 解析器是操作 XML 文档的正确方法。
xmlstarlet解决方案:
xmlstarlet sel -t -c '//capacity[1]' -n yourxml > temp.txt
&& xmlstarlet ed -d '//capacity[1]' yourxml > tmp.xml && mv tmp.xml yourxml
cat temp.txt
<capacity><name>45.90</name>
<index>0</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>
xmlstarlet sel -t -c '//capacity[1]' -n yourxml > temp.txt
- 提取第一个capacity
标签声明并将输出重定向到temp.txt
xmlstarlet ed -d '//capacity[1]' yourxml > tmp.xml
capacity
-从文档中删除第一个标签(通过-d
删除操作)并将修改后的文档内容重定向到临时文件tmp.xml
mv tmp.xml yourxml
- 用修改后的版本替换初始 xml 文档
答案2
由于您没有 xml 解析器,请使用 gnu awk 尝试一下:
$ awk -v RS="<subcolumns>|</capacity>" 'NR==2{gsub(/^\n/,"");print $0 RT;exit}' file.xml
<capacity><name>45.90</name>
<index>0</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>
为什么这样有效:
在 awk 中,您可以设置自定义记录/行分隔符。在我们的示例中,我们使用<subcolumns>
或</capacity>
因此,通过自定义记录分隔符,我们可以实现以下格式:
$ awk -v RS="<subcolumns>|</capacity>" '{gsub(/^\n/,"");print NR,$0 RT}' file.xml
1 <subcolumns>
2 <capacity><name>45.90</name>
<index>0</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>
3 <capacity><name>57.09</name>
<index>1</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>
4 <capacity><name>55</name>
<index>2</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>
5 </subcolumns>
PS:NR = 数字或记录/行。 RT=使用的记录分隔符。
因此,您可以<capacity></capacity>
通过调整 NR 编号来打印任何块:
$ awk -v RS="<subcolumns>|</capacity>" 'NR==4{gsub(/^\n/,"");print $0 RT}'
<capacity><name>55</name>
<index>2</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>
因此,如果您需要跳过一个<capacity>
部分(即第一个容量部分),您可以执行以下操作:
$ awk -v RS="<subcolumns>|</capacity>" '{gsub(/^\n/,"")}NR!=2{print $0 RT}'
<subcolumns>
<capacity><name>57.09</name>
<index>1</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>
<capacity><name>55</name>
<index>2</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>
</subcolumns>
答案3
chunk=2; # specify the tag chunk number here which must be > 0
perl -l -0777ne "print((m{(<capacity>.*?</capacity>)}sg)[${chunk:-1}-1])" yourxmlfile
结果
<capacity><name>57.09</name>
<index>1</index>
<value_type>String</value_type>
<ignore_case_flag>1</ignore_case_flag>
<hidden_flag>0</hidden_flag>
<exclude_from_parse_flag>1</exclude_from_parse_flag>
</capacity>