我正在使用 sed 替换 XML 文件中的属性,到目前为止它工作得很好。
我有一个 XML 文件,其中包含如下标签:
<osgiApplication id="com.mycompany.site.app"
location="com.mycompany.site.app-1.0.0.20160406155451.eba"
name="com.mycompany.site.app" />
每当部署新的 EBA 文件时,都需要替换位置属性。例如:(不同的构建时间戳)
<osgiApplication id="com.mycompany.site.app"
location="com.mycompany.site.app-1.0.0.20160410173452.eba"
name="com.mycompany.site.app" />
我是通过使用sed
带有标签的表达式来做到这一点的:
:a;N;$!ba;0,s|<osgiApplication id="com.mycompany.site.app".*\/>|<osgiApplication id="com.mycompany.site.app" location="com.mycompany.site.app-1.0.0.20160406155451.eba"
它正在工作完美,直到我遇到另一种情况,我实际上还有其他标签<osgiApplication>
。例如:
<osgiApplication id="com.mycompany.site.app"
location="com.mycompany.site.app-1.0.0.20160406155451.eba"
name="com.mycompany.site.app" />
<anotherTag />
当发生这种情况时,由于.*\/>
sed 表达式中的标准,一切直到最后才被替换/>
。我只想替换第一个出现的位置。
换句话说,如果我有:
<osgiApplication id="com.mycompany.site.app"
location="com.mycompany.site.app-1.0.0.20160406155451.eba"
name="com.mycompany.site.app" />
<anotherTag />
<anotherTag />
<anotherTag />
我想要的替代品是:
<osgiApplication id="com.mycompany.site.app"
location="com.mycompany.site.app-1.0.0.20160410173452.eba"
name="com.mycompany.site.app" />
<anotherTag />
<anotherTag />
<anotherTag />
但我目前得到的是:
<osgiApplication id="com.mycompany.site.app"
location="com.mycompany.site.app-1.0.0.20160410173452.eba"
name="com.mycompany.site.app" />
我一直在寻找解决方案,但没有找到:(任何建议将不胜感激。谢谢
答案1
你的问题的最佳答案确实是规范的,不要使用 sed。除非问题是面向行的并且可以用 RE 表示,否则 sed 是错误的工具。您的情况是这样的:因为 XML 不是常规语言,任何如果考虑到足够的复杂性,RE 迟早会失败。唯一可靠的解决方案是使用 XML 解析器,例如 Python 标准库中的 SAX 解析器。
不管怎样,一个好的黑客值得另一个。如果您希望在研究 SAX 解析器时让脚本再次工作,您可以尝试两件事:限制性更强的 RE,或 awk。
更严格的 RE 可以([^/>]+)
代替.*
.您可能会被以 结尾的文件名烧毁>
,但您可以防止这种情况,我的猜测是制作者无论如何都不会创建这样的文件名。专业提示:当您寻找带有 的栅栏柱时.*
,请使用负字符类。
更好的选择是 awk,类似
# use awk -F '["]' to set FS to a double-quote character
/<osgiApplication id=.*app"/ {
APP=$2
next
}
APP && /location=/ {
if (index($2, APP) {
substr($2, REPLACEMENT, $0)
}
APP = ""
}
当找到合适的开始标记时,这会设置 APP,并将其替换为您提供的 REPLACMENT 命名的字符串。你可以多加小心,如果/[/]> *$/
在设置时遇到这样的情况,请重置APP并发出警告。但我们仍然只是在黑客攻击,因为 XML 中没有任何内容说明标签在行首/行尾处的开始和停止。