如何使用 sed 或 awk 替换特定的 xml 节点值
How to replace specific xml node value using sed or awk
我想用 sed
或 awk
替换特定的 xml 节点值。我不能使用专门的包来解析xml,比如xmlstarlet
、xmllint
等。我有使用 sed
或 awk
,只是“基本”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>
的位置或行号是每个文件都不同。
我认为解决方案是:
- 定位并提取 parent
<desc:desc ID="DESC_VOLUME_0001">
及其 children 到变量
- 迭代children并获取
<desc:partNumber>
的位置(行号)
和 <desc:dateIssued>
并保存到变量
- 将行号传递给
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.
的行(更改或其他方式)
我想用 sed
或 awk
替换特定的 xml 节点值。我不能使用专门的包来解析xml,比如xmlstarlet
、xmllint
等。我有使用 sed
或 awk
,只是“基本”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>
的位置或行号是每个文件都不同。
我认为解决方案是:
- 定位并提取 parent
<desc:desc ID="DESC_VOLUME_0001">
及其 children 到变量 - 迭代children并获取
<desc:partNumber>
的位置(行号) 和<desc:dateIssued>
并保存到变量 - 将行号传递给
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.
的行(更改或其他方式)