sed:仅替换第一次出现的通配符

sed:仅替换第一次出现的通配符

我正在使用 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 中没有任何内容说明标签在行首/行尾处的开始和停止。

相关内容