Today I Learned
Search…
Parsing changelogs using regex with Go
Posted on 08 Aug, 2021
Consider a sample CHANGELOG.md file like this
1
# Changelog
2
​
3
All notable changes to this project will be documented in this file.
4
​
5
## [0.4] - Nov 11, 2019
6
​
7
### Added
8
​
9
- `getSubmissionDate()`, `getExitCode` new methods.
10
- Official Documentation.
11
​
12
### Changed
13
​
14
- Class Run `init` - Now you can pass _source code_, _input_ and _output_ to program as strings (limited to file paths in prior versions).
15
​
16
​
17
## [0.3] - Nov 9, 2019
18
​
19
### Added
20
​
21
- Removed redundant imports
22
- Added Module/Class docstrings for documentation
23
- Formatted Code
24
​
25
​
26
## [0.2] - Oct 31, 2019
27
​
28
### Changed
29
​
30
- Fix import requests problem.
31
​
32
​
33
## [0.1] - Oct 30, 2019
34
- Initial Release
Copied!
The following golang code can be used to extract the changelog for a requested version
1
// Parse a changelog.md file and display changelog for a requested version
2
​
3
package main
4
​
5
import (
6
"fmt"
7
"io/ioutil"
8
"os"
9
"regexp"
10
"strings"
11
)
12
​
13
func Parse(match string, rem string) string {
14
// remove the enclosing pattern of previous release
15
temp := strings.TrimSuffix(match, rem)
16
return strings.Trim(temp, "\r\n")
17
}
18
​
19
func main() {
20
enclosingPattern := `## [`
21
var submatchall []string
22
// prefixing verion number 0.6 with v won't work
23
ver := "0.3"
24
// Every new version looks like this: ## [1.4.0] - Jan 12, 2069
25
// (?s) + <enclosing pattern> + <version-number> + .* + </enclosingPattern>
26
​
27
// (?s) : Make the dot match all characters including line break characters
28
// .* : . (dot) indicates any character whereas * specifies 0 or more instances of previous token
29
// var re = regexp.MustCompile(`(?s)## \[0.6.*?## \[`)
30
var re = regexp.MustCompile(`(?s)` + `## \[` + ver + `.*?` + `## \[`)
31
​
32
data, err := ioutil.ReadFile("CHANGELOG.md")
33
if err != nil {
34
fmt.Println("File reading error", err)
35
}
36
fileContent := string(data)
37
submatchall = re.FindAllString(fileContent, 1)
38
if len(submatchall) == 1 {
39
fmt.Println(Parse(submatchall[0], enclosingPattern))
40
} else {
41
fmt.Println("No changelog or invalid version", ver)
42
os.Exit(1)
43
}
44
}
Copied!
Here is a sample output
1
$ go run changelog-parser.go
2
## [0.3] - Nov 9, 2019
3
​
4
### Added
5
​
6
- Removed redundant imports
7
- Added Module/Class docstrings for documentation
8
- Formatted Code
Copied!
Copy link
Edit on GitHub