英文:
How do I use multiline regex match in Jenkins / Groovy
问题
In Jenkins,我正在构建一个步骤,该步骤读取CHANGELOG.md并使用正则表达式从给定版本中提取最新的更改日志。
用到的.groovy代码:
def currentTag = '0.1.0'
def changelogFileName = 'CHANGELOG.md'
def changelogText = readFile(file: changelogFileName)
def pattern = "(?s)^## ${currentTag}.*?(?=\\n\\n## |\\z)"
def matcher = (changelogText =~ pattern)
if (matcher.find()) {
    def latestChangelog = matcher.group()
    println(latestChangelog.strip())
} else {
    println('无法解析最新的更改日志。')
}
用到的输入文件:
# Changelog - 项目
所有显著的更改将在此文件中记录。
本项目遵循[语义化版本](http://semver.org/)。
根据[Keep a CHANGELOG](http://keepachangelog.com/)的准则编写的更改日志。
## 0.3.0 - 2022-06-30
### 更改:
- MDN-XXXX: blabla
### 还有更改:
- MDN-XXXX: blabla
## 0.2.0 - 2022-06-09
### 添加:
- MDN-XXXX: blabla
## 0.1.1 - 2022-06-08
### 修复:
- MDN-XXXX: blabla
## 0.1.0 - 2022-06-08
### 添加:
 - MDN-XXXX: blabla
 - MDN-XXXX: blabla
在本地,此代码运行得很好。
但是,我想在Jenkins中使用它,那里直接导入这些内容会存在安全问题:
import java.nio.file.Files
import java.nio.file.Paths
import java.util.regex.Pattern
因此,我需要将其更改为适用于Jenkins的代码。
所以我将它更改为以下内容:
def changelogText = readFile(file: changelogFileName)
def pattern = "(?s)^## ${currentTag}.*?(?=\\n\\n## |\\z)"
def matcher = (changelogText =~ pattern)
if (matcher.find()) {
    def latestChangelog = matcher.group()
    println(latestChangelog.strip())
} else {
    println('无法解析最新的更改日志。')
}
但是,我一直收到'无法解析最新的更改日志。'的消息。
当我不得不一直在Jenkins上运行它时,调试起来非常困难。
是否有人知道如何在本地使Jenkins库可用,或者更好的是,如何使用Pattern.MULTILINE进行匹配?
或者对于完全不同的方法是否有建议?
英文:
In Jenkins I'm building a step that reads CHANGELOG.md and uses regex to extract the latest changelog from giving version.
The used .groovy code:
#!/usr/bin/env groovy
import java.nio.file.Files
import java.nio.file.Paths
import java.util.regex.Pattern
def String currentTag = '0.1.0';
def String changelogFileName = 'CHANGELOG.md';
def changelogText = new String(Files.readAllBytes(Paths.get(changelogFileName)))
def pattern = Pattern.compile("(?s)^## ${currentTag}.*?(?=\n\n## |\\z)", Pattern.MULTILINE)
def matcher = pattern.matcher(changelogText)
if (matcher.find()) {
    def latestChangelog = matcher.group()
    println latestChangelog.strip()
}
The used input file:
# Changelog - Project
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
Changelog based on guidelines from
[Keep a CHANGELOG](http://keepachangelog.com/).
## 0.3.0 - 2022-06-30
### Changed:
- MDN-XXXX: blabla
### Also Changed:
- MDN-XXXX: blabla
## 0.2.0 - 2022-06-09
### Added:
- MDN-XXXX: blabla
## 0.1.1 - 2022-06-08
### Fixed:
- MDN-XXXX: blabla
## 0.1.0 - 2022-06-08
### Added:
 - MDN-XXXX: blabla
 - MDN-XXXX: blabla
Locally this code works great.
However, I want to use it in Jenkins, and there it's a security issues to directly import these:
import java.nio.file.Files
import java.nio.file.Paths
import java.util.regex.Pattern
Hence, I need to change it to Jenkins friendly code.
So I changed it to this:
    def changelogText = readFile(file: changelogFileName)
    def pattern = "(?s)^## ${currentTag}.*?(?=\n\n## |\\z)"
    def matcher = (changelogText =~ pattern)
    if (matcher.find()) {
        def latestChangelog = matcher.group();
        println(latestChangelog.strip());
    } else {
        println('Could not parse latest changelog.');
    }
However, I keep getting 'Could not parse latest changelog.'
It's quite hard to debug when I have to run it on Jenkins the whole time.
Does anyone know how to make the Jenkins libraries available locally, or better, how I can match using Pattern.MULTILINE?
Or perhaps a suggestion for a whole different approach?
答案1
得分: 1
以下是您要翻译的内容:
如果有人想要使用 awk,这是一个 awk 解决方案,但我仍然更喜欢上面的解决方案,因为如果最后一个条目 0.1.0 中有空行的话,它更好。
#!/usr/bin/env groovy
/**
 * 从给定的文件名和标签获取最新的更改日志数据
 * @param currentTag 字符串
 * @param changelogFileName 字符串
 */
def call(
    String currentTag = '0.1.0',
    String changelogFileName = 'CHANGELOG.md'
) {
    def changelogText  = sh(returnStdout: true, script: "awk '{ RS=\"\" } /## ${currentTag}.*?(^## |$)/' ${changelogFileName}").strip();
    if (changelogText) {
        return changelogText;
    } else {
        return "无法解析 ${changelogFileName} 中标签 ${currentTag} 的更改日志。更改日志已推送吗?或者更改日志可能包含语法错误?";
    }
}
希望这有所帮助!如果您需要进一步的翻译,请告诉我。
英文:
In case someone wants to use awk instead, this in an awk solution, however, I still prefer the above one as it's better in case if the last entry 0.1.0 has some empty lines in it.
#!/usr/bin/env groovy
/**
 * Get latest changelog data from given filename and tag
 * @param currentTag string
 * @param changelogFileName string
 */
def call(
    String currentTag = '0.1.0',
    String changelogFileName = 'CHANGELOG.md'
) {
    def changelogText  = sh(returnStdout: true, script: "awk '{ RS=\"\" } /## ${currentTag}.*?(^## |$)/' ${changelogFileName}").strip();
    if (changelogText) {
        return changelogText;
    } else {
        return "Could not parse the changelog of tag ${currentTag} in ${changelogFileName}. Is changelog pushed? Or perhaps the changelog contains a syntax error?";
    }
}
答案2
得分: 1
要匹配包括换行符在内的所有符号,您可以使用 [\s\S]。这将在没有任何标志的情况下工作。
考虑以下示例:
String changelogText = """
# Changelog - Project
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
Changelog based on guidelines from
[Keep a CHANGELOG](http://keepachangelog.com/).
## 0.3.0 - 2022-06-30
### Changed:
- MDN-XXXX: blabla
### Also Changed:
- MDN-XXXX: blabla
## 0.2.0 - 2022-06-09
### Added:
- MDN-XXXX: blabla
## 0.1.1 - 2022-06-08
### Fixed:
- MDN-XXXX: blabla
## 0.1.0 - 2022-06-08
### Added:
 - MDN-XXXX: blabla
 - MDN-XXXX: blabla
"""
def currentTag = "0.2.0 - 2022-06-09"
def pattern = /## ${currentTag}[\s\S]*?(?=\n\n## |\z)/
def matcher = (changelogText =~ pattern)
if (matcher.find()) {
    def latestChangelog = matcher[0];
    println(latestChangelog);
} else {
    println('Could not parse latest changelog.');
}
输出:
## 0.2.0 - 2022-06-09
### Added:
- MDN-XXXX: blabla
英文:
To match all symbols including newlines, you can use [\s\S]. This will work without any flags.
Consider the following demo:
String changelogText = """
# Changelog - Project
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
Changelog based on guidelines from
[Keep a CHANGELOG](http://keepachangelog.com/).
## 0.3.0 - 2022-06-30
### Changed:
- MDN-XXXX: blabla
### Also Changed:
- MDN-XXXX: blabla
## 0.2.0 - 2022-06-09
### Added:
- MDN-XXXX: blabla
## 0.1.1 - 2022-06-08
### Fixed:
- MDN-XXXX: blabla
## 0.1.0 - 2022-06-08
### Added:
 - MDN-XXXX: blabla
 - MDN-XXXX: blabla
"""
def currentTag = "0.2.0 - 2022-06-09"
def pattern = /## ${currentTag}[\s\S]*?(?=\n\n## |\z)/
def matcher = (changelogText =~ pattern)
if (matcher.find()) {
    def latestChangelog = matcher[0];
    println(latestChangelog);
} else {
    println('Could not parse latest changelog.');
}
Output:
## 0.2.0 - 2022-06-09
### Added:
- MDN-XXXX: blabla
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论