我正在寻找创建一个快速shell脚本(HP-UX系统)来根据简单的测试条件删除XML标记。我不能使用像'xmlstarlet'这样的XML识别工具,因为这些工具由于多种原因而无法在我的生产系统上使用。我确实意识到这些是正确的方法,但我在此事上别无选择。
考虑以下两个与两个设备相关的XML元素。当设备没有通信时,将没有StationId且没有HardwareInv,标签在结尾处与<..../>
不同。当设备处于通信状态时,会出现StationId并且可以使用HardwareInv内容,开始/结束标记已完成,即结束时为</....>
。
我希望通过搜索<StationId/>
和/或<HardwareInv/>
来查找和删除设备以外的设备,如果找到,则完全删除相关DeviceA标记之间的所有内容,包括DeviceA标记他们自己不留空白。
我特别尝试了使用'sed'的不同结果的一些事情,但没有100%成功。非常感谢您的帮助。
这是输入XML文件:
<DeviceA>
<PhysicalAdd>10.10.10.69</PhysicalAdd>
<NEId>0000-Test-06</NEId>
<StationId/>
*** MORE CONTENT REMOVED ***
<HardwareInv/>
</DeviceA>
<DeviceA>
<PhysicalAdd>10.10.10.109</PhysicalAdd>
<NEId>0000-Test-13</NEId>
<StationId>Bravo-01</StationId>
*** MORE CONTENT REMOVED ***
<HardwareInv>
<Unit>
<UnitId>1</UnitId>
<SerialNumber>1389A</SerialNumber>
</Unit>
</HardwareInv>
</DeviceA>
预期产出:
<DeviceA>
<PhysicalAdd>10.10.10.109</PhysicalAdd>
<NEId>0000-Test-13</NEId>
<StationId>Bravo-01</StationId>
*** MORE CONTENT REMOVED ***
<HardwareInv>
<Unit>
<UnitId>1</UnitId>
<SerialNumber>1389A</SerialNumber>
</Unit>
</HardwareInv>
</DeviceA>
答案 0 :(得分:0)
此脚本非常简单,可以与任何版本的awk一起使用:
read()
它检测起始标记并将两个布尔值设置为false,0和true,1,并清除字符串变量with open("global_users.txt", "r") as f:
for data in f:
if data == username_ask:
print(G+"Success!")
password_ask = raw_input(O+"Password:"+W+" ")
with open("global_passwords.txt", "r") as f:
for line in f:
data = f.read()
if data == password_ask:
print(G+"Success!")
else:
print(R+"Incorrect Password!")
else:
print(R+"No Users Found!")
。
找到空标记后,awk '
/<DeviceA>/ { found = 0; tosave = 1; save = "" }
/<HardwareInv\/>/ || /<StationId\/>/ { found = 1 }
/<DeviceA>/,/<\/DeviceA>/ { save = save $0 "\n" }
tosave==0 { print }
/<\/DeviceA>/ { if(!found)printf "%s",save; tosave = 0 }
'
布尔值设置为true。
要删除的组的开始和结束标记之间的所有行都在字符串变量中累积,它们之间有换行符。
如果不保存行,则打印它们。当结束标记匹配时, 如果未找到空标签,则打印已保存的组,然后停止保存。
代码中存在一些冗余,但它是为了保持简单。显然,它只处理你给出的格式的数据,而不是任何xml。
答案 1 :(得分:0)
对于多字符RS,使用GNU awk会更简洁:
$ awk -v RS='</DeviceA>\\s*' -v ORS= '/<StationId>/{print $0 RT}' file
<DeviceA>
<PhysicalAdd>10.10.10.109</PhysicalAdd>
<NEId>0000-Test-13</NEId>
<StationId>Bravo-01</StationId>
*** MORE CONTENT REMOVED ***
<HardwareInv>
<Unit>
<UnitId>1</UnitId>
<SerialNumber>1389A</SerialNumber>
</Unit>
</HardwareInv>
</DeviceA>
但是对于任何awk,你只需要逐行建立记录:
$ cat tst.awk
{ rec = (rec=="" ? "" : rec ORS) $0 }
/<\/DeviceA>/ {
if (rec ~ /<StationId>/) {
print rec
}
rec = ""
}
$ awk -f tst.awk file
<DeviceA>
<PhysicalAdd>10.10.10.109</PhysicalAdd>
<NEId>0000-Test-13</NEId>
<StationId>Bravo-01</StationId>
*** MORE CONTENT REMOVED ***
<HardwareInv>
<Unit>
<UnitId>1</UnitId>
<SerialNumber>1389A</SerialNumber>
</Unit>
</HardwareInv>
</DeviceA>