如何合并sed命令批量修改XML文件适配SonarQube?
合并sed命令并转换XML适配SonarQube
需求概述
Mac环境下,需将个人项目的XML覆盖率文件修改格式以适配SonarQube。当前已有多个分散的sed命令实现部分需求,希望合并为更少的文件操作;尝试过xmlstarlet,但会删除整个节点块,仅需删除特定行。需完成的具体修改:
- 合并删除命令(利用sed的OR逻辑)
- 将
class替换为file - 修改
<coverage>行的version值为1 - 额外适配:将
<line>转换为<lineToCover>、调整相关属性名(如line-rate→lineToCover-rate等)
现有分散命令
# 删除特定行 sed -i '' '/classes/d' coverage.xml sed -i '' '/lines>/d' coverage.xml sed -i '' '/<method/d' coverage.xml sed -i '' '/package/d' coverage.xml sed -i '' '/source/d' coverage.xml sed -i '' '/<source/d' coverage.xml # 替换class为file sed -i '' 's/class/file/g' coverage.xml # 修改coverage版本 sed -i '' '/<coverage/s/version="2.0.3"/version="1"/g' coverage.xml
原始XML
<?xml version="1.0" ?> <!DOCTYPE coverage SYSTEM 'http://cobertura.sourceforge.net/xml/coverage-04.dtd'> <coverage branch-rate="0.0" branches-covered="0" branches-valid="0" complexity="0" line-rate="0.5936254980079682" lines-covered="447" lines-valid="753" timestamp="1672197709" version="2.0.3"> <packages> <package line-rate="0.7614678899082569" branch-rate="0.0" name="src.services.secrets.keys" complexity="0"> <classes> <class branch-rate="0.0" complexity="0" filename="src/services/guava/keys/keys.go" line-rate="0.7614678899082569" name="src.services.guava.keys.keys.go"> <methods/> <lines> <line branch="false" hits="0" number="109"/> <line branch="false" hits="0" number="123"/> </lines> </class> </classes> </package> <package line-rate="0.5944055944055944" branch-rate="0.0" name="src.services.guava.vault" complexity="0"> <classes> <class branch-rate="0.0" complexity="0" filename="src/services/secrets/vault/vault.go" line-rate="0.5944055944055944" name="src.services.guava.vault.vault.go"> <methods/> <lines> <line branch="false" hits="1" number="251"/> <line branch="false" hits="1" number="253"/> </lines> </class> </classes> </package> </packages> </coverage>
期望适配SonarQube的XML
<?xml version="1.0" ?> <!DOCTYPE coverage SYSTEM 'http://cobertura.sourceforge.net/xml/coverage-04.dtd'> <coverage branch-rate="0.0" branches-covered="true" branches-valid="0" complexity="0" lineToCover-rate="0.5936254980079682" lineToCovers-covered="447" lineToCovers-valid="753" timestamp="1672173715" version="1"> <file branch-rate="0.0" complexity="0" path="src/services/guava/keys/keys.go" lineToCover-rate="0.7614678899082569" name="src.services.guava.keys.keys.go"> <lineToCover branch="false" covered="false" lineNumber="16"/> <lineToCover branch="false" covered="false" lineNumber="17"/> </file> <file branch-rate="0.0" complexity="0" path="src/services/guava/server/server.go" lineToCover-rate="0.744" name="src.services.guava.server.server.go"> <lineToCover branch="false" covered="false" lineNumber="153"/> </file> <file branch-rate="0.0" complexity="0" path="src/services/secrets/tools/keyrotate/cmd_get.go" lineToCover-rate="0.0" name="src.services.guava.tools.keyrotate.cmd_get.go"> <lineToCover branch="false" covered="true" lineNumber="16"/> </file> <file branch-rate="0.0" complexity="0" path="src/services/secrets/tools/keyrotate/cmd_rotate.go" lineToCover-rate="0.72" name="src.services.guava.tools.keyrotate.cmd_rotate.go"> <lineToCover branch="false" covered="false" lineNumber="75"/> </file> <file branch-rate="0.0" complexity="0" path="src/services/secrets/tools/keyrotate/main.go" lineToCover-rate="0.0" name="src.services.guava.tools.keyrotate.main.go"> <lineToCover branch="false" covered="true" lineNumber="80"/> <lineToCover branch="false" covered="true" lineNumber="81"/> </file> <file branch-rate="0.0" complexity="0" path="src/services/guava/vault/vault.go" lineToCover-rate="0.5944055944055944" name="src.services.guava.vault.vault.go"> <lineToCover branch="false" covered="false" lineNumber="251"/> <lineToCover branch="false" covered="false" lineNumber="253"/> </file> </coverage>
优化后的单条sed命令
将所有操作合并为一次文件读写,利用sed的\|实现OR逻辑匹配删除行,通过-e参数串联多个修改动作:
sed -i '' -e '/classes\|lines>\|<method\|package\|source\|<source/d' \ -e 's/class/file/g' \ -e '/<coverage/s/version="2.0.3"/version="1"/g' \ -e 's/line-rate/lineToCover-rate/g' \ -e 's/lines-covered/lineToCovers-covered/g' \ -e 's/lines-valid/lineToCovers-valid/g' \ -e 's/filename="/path="/g' \ -e 's/<line branch="\([^&]*\)" hits="\([0-9]*\)" number="\([0-9]*\)"/<lineToCover branch="\1" covered="\2" lineNumber="\3"/g' coverage.xml
命令说明
- 删除行:用
\|分隔所有需要删除的行匹配模式,一次删除所有目标行 - 替换class为file:全局替换所有
class字符串为file - 修改coverage版本:仅匹配
<coverage>行,替换版本号 - 调整属性名:将SonarQube不兼容的属性名替换为目标格式
- 转换行节点:将
<line>节点转换为<lineToCover>,并调整属性(hits转covered,number转lineNumber)
内容的提问来源于stack exchange,提问作者AhmFM
相关产品推荐
相关产品推荐

