如何使用 sed 或 awk 替换特定的 xml 节点值

How to replace specific xml node value using sed or awk

我想用 sedawk 替换特定的 xml 节点值。我不能使用专门的包来解析xml,比如xmlstarletxmllint等。我有使用 sedawk,只是“基本”shell.

我有很多大 xml 文件。在该文件中,我想定位并替换两个标签值:示例:

<desc:partNumber>>2</desc:partNumber>
<desc:dateIssued>>1870</desc:dateIssued>

问题是,有数百个标签具有这些名称。但是这两个标签有 parent 标签,在整个 xml 文件中是唯一的:

<desc:desc ID="DESC_VOLUME_0001">

另一个问题是 parent <desc:desc ID="DESC_VOLUME_0001"> 中的标签 <desc:partNumber><desc:dateIssued> 的位置或行号是每个文件都不同

我认为解决方案是:

  1. 定位并提取 parent <desc:desc ID="DESC_VOLUME_0001"> 及其 children 到变量
  2. 迭代children并获取<desc:partNumber>的位置(行号) 和 <desc:dateIssued> 并保存到变量
  3. 将行号传递给sed命令并替换当前值 具有新值的标签(新值将从 .csv 文件中读取)

我尝试创建此 sed 命令,您可以看到我使用“n”来移动行,但这需要可变。

sed -i '/desc:desc ID="DESC_VOLUME_0001"/{n;n;n;n;n;n;n;n;n;s/'"${OLD_DATE_ISSUED}"'/'"${NEW_DATE_ISSUED}"'/}'

Parent 节点 children:

<desc:desc ID="DESC_VOLUME_0001"> 
    <desc:physicalDescription> 
        <desc:note>text</desc:note> 
    </desc:physicalDescription>  
    <desc:titleInfo> 
        <desc:partNumber>2</desc:partNumber> 
    </desc:titleInfo>  
    <desc:originInfo> 
        <desc:dateIssued>1870</desc:dateIssued> 
    </desc:originInfo>  
    <desc:identifier type="uuid">81e32d30-6388-11e6-8336-005056827e52</desc:identifier> 
</desc:desc> 

任何人都可以帮助实现这一目标吗?

使用文件 xmldata 中的示例数据:

awk -v dID="DESC_VOLUME_0001" -v part="5" -v dissue=1850 -F[\<\>] 
  ' ~ /desc ID/ { 
                     split(,arr,"\"");
                     descID=arr[2] 
                  } 
    ~ /desc:partNumber/ { 
                            if (descID==dID) { 
                                               [=10=]=gensub(,part,[=10=]) 
                                             } 
                          } 
    ~ /desc:dateIssued/ { 
                            if (descID==dID) 
                                             { 
                                               [=10=]=gensub(,dissue,[=10=]) 
                                             } 
                          }
   1' xmldata

一个班轮:

 awk -v dID="DESC_VOLUME_0001" -v part="5" -v dissue=1850 -F[\<\>] ' ~ /desc ID/ { split(,arr,"\"");descID=arr[2] }  ~ /desc:partNumber/ { if (descID==dID) { [=11=]=gensub(,part,[=11=]) } }  ~ /desc:dateIssued/ { if (descID==dID) { [=11=]=gensub(,dissue,[=11=]) } }1' xmldata

这里我们将分隔符设置为<或>我们还将dID设置为我们要搜索的desc ID,part为我们要更改的partNumber和dissue为我们要更改的dateIssued。

然后我们在行中搜索desc ID文本,并根据双引号拆分行,得到数组arr的第二个索引,然后用于创建变量descID。

我们进一步搜索 partNumber 和 dateIssued,检查是否 dID=descID。如果它们匹配,我们使用 gensub 函数将 $0 行中的第三个分隔字段替换为传递的变量,并将 $0 设置为结果。我们最终打印了通过 1.

的行(更改或其他方式)