【发布时间】:2018-02-20 17:48:49
【问题描述】:
问题描述:
考虑下面的 XML 文件:
<xmlhead1> <xmlsubhead1> <record> <field>Hello</field> <field>World</field> </record> <record> <field>DELETEKEY</field> <field>World1</field> </record> </xmlsubhead1> </xmlhead1>我的目标是删除一个“记录”XML标签,当字段子标签 该 XML 节点的 包含 DELETEKEY 作为值。
所以在上面的 XML 文件中我将删除
<record> <field>DELETEKEY</field> <field>World1</field> </record>
选择的解决方案:
我尝试使用 GNU sed 来解决上述问题:
下面是我的代码。
sed -n '
/<xmlhead1>/,/<\/xmlhead1>/{
/<xmlsubhead1>/,/<\/xmlsubhead1>/{
/<record>/,/<\/record>/{
#Append to hold space
H
#if match DELETEKEY, start delete processing for the xml <record> element
/<field>DELETEKEY<\/field>/{
s/.*//g ; x
b delete
}
#if you have reached the end tag of the <record> element,
#print the hold space and clear the buffers
/<\/record>/{
g ; s/^\n//g; p
s/.*//g ; x ; s/.*//g
}
#continue to next line
b
#delete processing
:delete
{
#clear pattern space.
s/.*//g
#Read Next Line and remove new line(\n)
N
s/^\n//g
#end delete processing when line matches the end tag </record>
/<\/record>/b
#else continue to get next line for delete process
b delete
}
}
}
}
#print all other lines
p
' $inputfile
逻辑如下:
- 匹配以
<xmlhead1> and ending with </xmlhead1>开头的地址范围- 匹配内部地址范围以
<xmlsubhead1> and ending with </xmlsubhead1>- 匹配内部地址范围
<record> to </record>- 当在
<record>标签内时,
(i) 将所有行追加到保持空间。
(ii) 如果该行匹配DELETEKEY,则必须删除该记录。执行步骤 iii 和 iv。否则,如果没有匹配,请转到步骤 v
(iii)对于delete,清空hold space并跳转到delete分支
(iv) 在删除分支中,使用“N”命令读取所有下一行,直到遇到</record>。当</record>是 遇到,退出循环,开始处理下一个 线。
(v) 不处理删除逻辑时,如果遇到</record>,则表示<record> to </record>的块是 已成功处理并存在于保留空间中。
(vi) 所以把它从存放空间中取出并打印出来。
上述逻辑的输出:
<xmlhead1>
<xmlsubhead1>
<record>
<field>Hello</field>
<field>World</field>
</record>
</xmlhead1>
输出中的问题:
您会注意到带有 DELETEKEY 的记录元素已被删除,但输出中缺少 </xmlsubhead1> 标记。
问题调试:
在调试时我发现在删除处理中遇到</record> 行后,在<record> to </record> 范围内,内部地址范围匹配应该已经结束,因为我已经读取并处理了</record> 行。
但<record> to </record> 范围块似乎也处理</xmlsubhead1> 行。
我通过在<record> 范围的命令块中添加以下代码发现了这一点。
/<record>/,/<\/record>/{
/<\/recordList>/{
s/.*/record list is inside the record to record range/g
p
}
有人可以解释 sed 的这种行为,即范围匹配超出了实际匹配吗?在这种情况下<record> to </record> range match is also matching </xmlsubhead1>
【问题讨论】:
-
你使用正则表达式而不是像
xmlstarlet这样的正确的XML感知工具有什么原因吗? -
没有理由。我只是想在 sed 中实现并偶然发现了上述行为。似乎很奇怪。虽然稍后我将使用其他工具来实际解决问题,但我想知道为什么 sed 的行为似乎如上所述。
标签: sed text-processing