我有一个 Jenkinsfile 文件,它会分析一些本地的 artifactory 服务器,以查找父组件和依赖项的新版本。当我确认有新版本时,我想用新版本替换旧版本。
因此给定一个包含此依赖项的 pom.xml:
<dependency>
<groupId>abcde</groupId>
<artifactId>xyz</artifactId>
<version>1.2.4</version>
</dependency>
...并假设 abcde.xyz 有一个较新版本 1.3.5...
我想使用以下 sed 命令来更新它:
sed -i '/<dependency>/,/<\/dependency>/{
/<groupId>abcde<\/groupId>/{
/<artifactId>xyz<\/artifactId>/{
s/<version>1.2.4<\/version>/<version>1.3.5<\/version>/
}
}
}' pom.xml
如果我创建一个包含上述 xml 或仅包含上述 xml 的 pom.xml 并执行此语句,则会修改该文件,但不会更改任何内容。删除该-i
标志基本上会将文件 1:1 转储到 stdout - 我遗漏了什么?
预期输出:
<dependency>
<groupId>abcde</groupId>
<artifactId>xyz</artifactId>
<version>1.3.5</version>
</dependency>
(在 jenkinsfile 中它被参数化并像下面这样转义,但由于基本语句不起作用,请关注这一点。)
sh """
sed -i '/<dependency>/,/<\\/dependency>/{
/<groupId>${groupId}<\\/groupId>/{
/<artifactId>${artifactId}<\\/artifactId>/{
s/<version>${version}<\\/version>/<version>${targetVersion}<\\/version>/
}
}
}' pom.xml
"""
如果直接在shell中执行,
sed 's/${groupId}/foo/'
变量groupId
不会被展开,因为它在单引号内。当你sh """ ... """
在运行它时,用单引号括起来,也可能会遇到这种情况(“jenkinsfile”?),我不知道。/<dependency>/,/<\/dependency>/{ foo }
意思是“针对从 到的每一行/<dependency>/
执行。因此,您要隔离感兴趣的行块,但仍然在该块内一次应用一行。然后,您要执行与该行匹配的操作,然后尝试在该行内执行,但由于 不存在于同一行,因此永远不会执行任何操作。/<\/dependency>/
foo
foo
/<groupId>abcde<\/groupId>/
/<artifactId>xyz<\/artifactId>/
<artifactId>
<groupId>
您可以轻松、更稳健地完成此操作,而无需使用 awk 重复任何块开始/结束表达式,例如使用带有 GNU awk 的小型状态机
-i inplace
(我假设您已经拥有它,因为您正在使用 GNU sed):除了按照您的要求解决 sed 无法进行文字字符串比较并因此要求您转义所有正则表达式元字符、sed 分隔符和反向引用的问题之外,请参阅是否可以使用 sed 可靠地转义正则表达式元字符。
更新 sed 地址以包含剩余的行,直到
</dependency>
达到目的美元符号也可以在内部地址上使用,以指示活动空间的结束,并且命令
/
上的分隔符s
可以用另一个字符替换,以减少转义