在 KSH 中查找文件元素

在 KSH 中查找文件元素

请帮我弄清楚我做错了什么。

我有一个名为“res.xml”的文件

<sequence type="a">
  <transaction>
   <branchSerial>1</branchSerial>
   <postingDate>2021-08-02</postingDate>
   <postingTime>2021-08-06 19:42:49 UTC</postingTime>
   <step type="a">
    <record type="c" label="deviceRecord">
     <operation option="V">View</operation>
     <tableName>DEVICE</tableName>
     <tableDescription>Device</tableDescription>
     <rowDescription>[email protected]</rowDescription>
    </record>
   </step>
  </transaction>
 </sequence>

我正在尝试提取 postsDate 并将其放入变量中。我的脚本:

#!/bin/ksh


dbDATE=$(sed -n -e "s/<postingDate>\([0-9]*\)<\/postingDate>/\1/p" res.xml)

  echo "current DB date: $dbDATE"

当我运行它时,我什么也没得到,只是空白。

这很奇怪,因为我在其他地方使用了相同的逻辑,没有出现任何问题。有人能看到我缺少什么吗???

非常感谢您提供的任何帮助

答案1

您的方法的主要问题sed是您不允许日期包含破折号。


要从显示的文件中提取数据,您可以在命令行中使用支持 XML 的解析器。

此类解析器的一个示例是xmlstarlet,您可以像这样使用它:

dbDATE=$( xmlstarlet sel -t -v '/sequence/transaction/postingDate' res.xml )

或者,如果您要查找其值的节点是唯一的此类节点,

dbDATE=$( xmlstarlet sel -t -v '//postingDate' res.xml )

另一个支持 XML 的解析器是xq,一个围绕 JSON 解析器的 XML 解析器包装器jq

dbDATE=$( xq -r '.sequence.transaction.postingDate' res.xml )

以上所有内容均假设sequence节点仅包含一个单一的 transaction节点。我们是否想要支持多个事务(“序列”一词暗示这可能包含一个列表交易),您还需要决定是否要选择第一的交易或给定某些其他条件的特定交易。

branchSerial假设我们想要价值为 的交易1。和xmlstarlet

dbDATE=$( xmlstarlet sel -t -v '/sequence/transaction[branchSerial=1]/postingDate' res.xml )

xq

dbDATE=$( xq -r '.sequence.transaction[] | select(.branchSerial == "1").postingDate' res.xml )

答案2

假设您将 .xml 输出设置为变量,您可以执行以下操作:

xmlData='
<sequence type="a">
  <transaction>
   <branchSerial>1</branchSerial>
   <postingDate>2021-08-02</postingDate>
   <postingTime>2021-08-06 19:42:49 UTC</postingTime>
   <step type="a">
    <record type="c" label="deviceRecord">
     <operation option="V">View</operation>
     <tableName>DEVICE</tableName>
     <tableDescription>Device</tableDescription>
     <rowDescription>[email protected]</rowDescription>
    </record>
   </step>
  </transaction>
 </sequence>
'

date=$(echo "$xmlData" | grep "postingDate" | tr '>' " " | tr '<' " " | awk '{print $2}')

既然你说你是从文件中提取它,你甚至可以这样做:

date=$(cat res.xml | grep "postingDate" | tr '>' " " | tr '<' " " | awk '{print $2}')

答案3

使用以下命令可以正常工作

dbdate=$(awk -F "[<>]" '/postingDate/{print $3}' res.xml)

echo -e "current DB date: $dbdate"
current DB date: 2021-08-02

相关内容