CI场景下用Bash正则修改Gradle文件prod渠道versionName的问题
解决Gradle中Pro渠道VersionName的正则替换问题
看来你在CI流程里替换Pro flavor的versionName时遇到了多行匹配的坑,原来的正则因为没考虑Gradle的多行结构和代码块范围,所以不好使。我来给你捋捋靠谱的解决方案:
问题根源
你原来用的(pro)(.*)((versionName) .*)有两个核心问题:
- 默认情况下
.不会匹配换行符,所以跨多行的pro块内容根本抓不到 - 没有限定只在
pro { ... }这个代码块内匹配,很可能误改其他flavor的配置
正确的正则与替换方案
我们需要精准定位到pro flavor的代码块内,再替换其中的versionName。下面分不同CI常用工具给你示例:
1. 使用Sed(适合Linux/macOS环境)
Sed的范围匹配功能可以直接限定修改范围,不需要复杂正则,简单粗暴:
# 把NEW_VERSION替换成你实际要设置的版本号,比如"2.0.1" sed -E '/pro\s*\{\s*/,/\}/ s/(versionName\s+)"[^"]+"/\1"NEW_VERSION"/' build.gradle
/pro\s*\{\s*/,/\}/:定义修改范围——从包含pro {(允许前后有空格、换行)的行开始,到第一个}结束s/(versionName\s+)"[^"]+"/\1"NEW_VERSION"/:在范围内替换versionName的引号内容,保留versionName前缀不变
2. 使用Python脚本(适合跨平台CI)
如果你的CI环境支持Python,这个方案更灵活精准,能应对更多格式变化:
import re # 读取Gradle文件内容 with open("build.gradle", "r", encoding="utf-8") as gradle_file: content = gradle_file.read() # 要设置的目标版本号 target_version = "2.1.0" # 正则匹配pro块内的versionName行 # re.DOTALL让.匹配换行,非贪婪模式确保只在pro块内匹配 pattern = re.compile( r'(pro\s*\{\s*(?:(?!\}).)*?versionName\s+)"[^"]+"', re.DOTALL ) # 执行替换 updated_content = pattern.sub(r'\1"%s"' % target_version, content) # 写回修改后的内容 with open("build.gradle", "w", encoding="utf-8") as gradle_file: gradle_file.write(updated_content)
正则规则拆解
上面Python里的正则各部分作用:
pro\s*\{\s*:匹配pro关键字,允许后面跟任意空格/换行,接着是左大括号{和后续空格/换行(适配pro和{同行或分行的情况)(?:(?!\}).)*?:非捕获组,非贪婪匹配任何字符,直到遇到}之前的内容(避免误匹配到其他flavor的代码块)versionName\s+"[^"]+":精准匹配versionName关键字、后续空格,以及引号包裹的版本号
注意事项
- 如果你的
pro块内有多个versionName(虽然正常Gradle配置不会这样),上面的方案会替换所有匹配项 - 在CI中执行时,建议先备份原文件,或者输出到临时文件再替换原文件,避免意外破坏配置
- 要是你的Gradle格式特别特殊(比如有嵌套大括号),可以调整正则里的非贪婪匹配逻辑进一步适配
内容的提问来源于stack exchange,提问作者Ricardo
相关产品推荐
相关产品推荐

