shell 解析更改日志并提取版本的更改

ttcibm8c  于 2022-11-16  发布在  Shell
关注(0)|答案(5)|浏览(178)

我在markdown中有一个changelog文件,其中包含了我的应用程序每个版本之间的所有更改,如下所示:

## Version 1.0.6

* first change
* second change
* third change

## Version 1.0.5

* first foo change
* second foo change

## Version 1.0.4

* and so on...

我想在一个脚本中提取一个版本的变更内容。例如,我想提取 * 版本1.0.5* 的变更,所以它应该输出:

* first foo change
* second foo change

理想的方式是./getVersionChanges version filename,其中包含以下两个参数:
version:要提取更改的版本
filename:要解析的文件名
如何使用sed、awk、grep或其他工具来实现这一点?

blpfk2vs

blpfk2vs1#

一个稍微复杂一点的awk解决方案

  • 一旦打印了感兴趣的块就退出,
  • 忽略空行,
  • 不包括标题行。
awk -v ver=1.0.5 '
 /^## Version / { if (p) { exit }; if ($3 == ver) { p=1; next } } p && NF
' file

作为脚本getVersionChanges

#!/usr/bin/env bash

awk -v ver="$1" '
 /^## Version / { if (p) { exit }; if ($3 == ver) { p=1; next } } p && NF
' "$2"

说明:

  • 正则表达式条件/^## Version /通过在行的开头(^)查找子字符串## Version,并在找到的情况下执行关联的代码块({ ... }),来匹配具有版本特定信息的行块的标题行:
  • 如果先前已经设置了p(打印)标志,则if (p) { exit }退出(停止处理),因为这意味着已经到达了感兴趣的块 * 之后 * 的块,即感兴趣的块现在已经被完全处理。
  • if ($3 == ver) { p=1; next }检查第三个空格分隔的字段($3)与给定的版本号匹配(通过选项-v ver=1.0.5传递,因此存储在变量ver中),并且如果是,则设置定制变量p,其用作指示是否打印行的标志,到1,并移动到下一行(next),以便不打印标题行本身。

换句话说就是:包含1p表示对于后续行,已经输入了感兴趣的版本特定的块,并且应当(潜在地)打印其行。

  • 条件p && NF在条件匹配时隐式打印手头的行,如果设置了打印标志p * 和 *,则会出现这种情况(&&)当前行至少有一个字段(基于内置变量NF中反映的字段数),即如果该行为 * 非空白 *,从而有效地跳过感兴趣的块中的空行和全空白行。
  • 请注意,&&的两个操作数都使用 * 隐式 * 布尔逻辑:0的值(诸如p的未初始化的定制变量默认为该值)隐式为假,而任何 * 非零 * 值隐式为真。
4szc88ey

4szc88ey2#

一个相当短的awk脚本将提取您想要的块。

#!/bin/sh

awk -v version="$1" '/## Version / {printit = $3 == version}; printit;' "$2"

样品:

$ ./getVersionChanges 1.0.5 filename
## Version 1.0.5

* first foo change
* second foo change

$
a6b3iqyw

a6b3iqyw3#

试试这个。您可以用您的文件名替换/tmp/data,用您的搜索模式替换“Version 1.0.5”。请注意,这不会删除任何空行。

sed  '1,/Version 1.0.5/d;/Version/Q' /tmp/data

输出量:

* first foo change
* second foo change

说明

默认情况下,sed会打印这些行,所以我们只需要修改逻辑,删除不需要的行。
选择线1和图案之间的所有内容并删除

1,/Version 1.0.5/d

找到模式后退出

/Version/Q
ff29svar

ff29svar4#

保留更改日志

我是在寻找从用keepachangelog约定编写的更改日志中提取一些发行说明的方法时发现这个线程的。
我对@mklement0的答案进行了修改,使其符合此约定。

shell

awk -v ver=1.0.5 '
 /^#+ \[/ { if (p) { exit }; if ($2 == "["ver"]") { p=1; next} } p && NF
' file

脚本

#!/usr/bin/env bash

awk -v ver="$1" '
 /^#+ \[/ { if (p) { exit }; if ($2 == "["ver"]") { p=1; next} } p && NF
' "$2"
qgelzfjb

qgelzfjb5#

在@mklement0的优秀答案的基础上,这里有一个相当粗糙的版本(请原谅我缺乏AWK脚本知识),它使用Conventional Changelog,假设:

  • #####开始版本行
  • 紧接着是空格和语义版本号,可以用括号括起来,也可以不用括号括起来(例如## 1.23.456## [1.23.456](http://github.com/etc)

不像OP,我...

  • 希望保留版本行(如果不希望保留版本行,请在p = 1之后添加next,如p = 1; next)。
  • 要保留换行符(如果要删除换行符,请在p之后添加NF,如p && NF
    更改日志.md
# Change Log

All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

## [1.23.456](https://github.com/your-org/your-repo/branches/compare/foo@1.23.456%foo@1.23.455) (2022-10-19)

**Note:** Version bump only for package foo

## 1.23.455 (2022-10-19)

**Note:** Version bump only for package foo

### Bug fixes

* **css:** Some style fix
* **js:** Some js fix
* **html:** Some html fix

### Features
* **js:** Some js feature

AWK

awk -v ver=5.1.30 '
 /^(##|###) \[?[0-9]+.[0-9]+.[0-9]+/ {
    if (p) { exit };
    if (index($2, "[")) {
        split($2, a, "[");
        split(a[2], a, "]");
        if (a[1] == ver) {
            p = 1
        }
    } else {
        if ($2 == ver) {
            p = 1
        }
    }
} p
' path/to/CHANGELOG.md

awk -v ver=1.23.456 ...

## [1.23.456](https://github.com/your-org/your-repo/branches/compare/foo@1.23.456%foo@1.23.455) (2022-10-19)

**Note:** Version bump only for package foo

awk -v ver=1.23.455 ...

## 1.23.455 (2022-10-19)

**Note:** Version bump only for package foo

### Bug fixes

* **css:** Some style fix
* **js:** Some js fix
* **html:** Some html fix

### Features
* **js:** Some js feature

相关问题