GNU Sed 版本历史(更新日志)——如何确定哪个版本引入了哪个特性?

mkl*_*nt0 5 version sed gnu

我发现了以下更改日志,但所有这些都根据日期而不是版本号列出了更改/新功能:

例如,我试图找出在哪个 GNUsed版本中引入了-z/--null-data选项,虽然上面告诉我 2012-02-05,但我无法确定映射到哪个版本号。

Soc*_*owi 5

有关列表,请参阅此答案的结尾。

上面告诉我 2012-02-05,我不知道映射到哪个版本号

要简单地将日期映射到版本号,您可以查看GNU sed 主页上的下载部分。在那里你有一个表格列表

Index of /gnu/sed
Name                   Last modified      Size
[...] 
sed-4.2.1.tar.gz       2009-06-27 18:22   1.1M   
sed-4.2.1.tar.gz.sig   2009-06-27 18:22   72 
sed-4.2.2.tar.gz       2012-12-22 11:01   1.3M   
sed-4.2.2.tar.gz.sig   2012-12-22 11:01   72     
[...]
Run Code Online (Sandbox Code Playgroud)

请注意,该列表按字母顺序排序,因此 4.24.2.1之后。您可以通过将其复制粘贴到sort -V.

假设每个更改都在下一个版本中,那么 2012-02-05 的更改将在 4.2.2 版本中发布。

确定在哪个版本中引入了哪些功能?

一般来说,这是非常棘手的。尽管ChangeLog-2014git log一起几乎覆盖整个生命周期的GNU sed的,不是每一个变化被提及。下一步是解析usage()旧版本的文档(联机帮助页和函数),但有时这些文档也不完整。

例一: -E 2004-08-22 4.2 版本首次出现,但在日志和官方文档中均未提及。该选项在 2013年 10 月 16 日(9 年多之后!)的 git commit 中首次提到,说“使用 ERE 的文档“-E”选项”

在其他情况下,变更日志可能非常具有误导性。

示例 2:Changelog-2014第一个参考中-r似乎是 2000-12-08 的条目,指出“sed/sed.c(main):Implemented the `r' and `R' options”。这听起来很确定:-r在此之前显然无法使用,对吧?!不,它已经是 1998 年的 3.0.1 版了。
不知道那个变更日志条目是怎么回事,但 3.0.1 版显然是 1998 年的(源文件的修改日期和他们的版权评论列表 1998 年是最后一年,更改日志还提到了 1998 年 3.0.1 的发布)并明确支持-r(我编译了该版本并运行了按预期./sed -r 's/a(b)c/\1/' <<< abc打印的版本b,并且abc省略了该-r选项)。

因此,似乎找出某个功能何时引入的最佳方法是检查所有版本的源代码。乍一看,这似乎令人生畏,但至少对于命令行选项而言,这非常简单:搜索main()函数并查看argv使用位置。

请注意,这git://git.sv.gnu.org/sed也是不完整的。最早的提交来自 2004 年(检查git log --reverse),最旧的标签v4.1.5标记了 2006 年的版本(检查git log --simplify-by-decoration --format="%ai %d")。因此,要检查旧版本,您必须从前面提到的网站下载它们。
甚至有些东西会随着时间的流逝而消失。4.0.0 到 4.0.5 版本“不可用,因为它们的真实性正在确认中”。但我想这并不重要,因为 4.0.0 与 4.0.6 相差不到一年。

幸运的是,GNU sed 的选项解析非常稳定,我可以一起破解一些东西来自动生成更改列表:

脚本(在此答案中压缩为一行到安全空间)...

#! /bin/bash
old=; curl -s "https://ftp.gnu.org/gnu/sed/" | sed -nE 's/.* href="sed-([0-9.]*)(\.tar\.[^."]*)".*([0-9]{4}-..-..).*/\1 \3 sed-\1\2/p' | sort -u -k1,1V | while read version date file; do printf '%-6s %s\n' "$version" "$date"; curl -sO -C- "https://ftp.gnu.org/gnu/sed/$file"; new=$(tar -xaf "$file" -O --wildcards '*/sed.c' | sed -En -e '/"[^" ]*e:[^" ]*"/{s/.*"([^" ]*e:[^" ]*)".*/\1/;s/://g;s/./\n-&/gp}' -e '/longopts\[]/,/};/s/[^"]*"([^"]*)".*/--\1/p' | sort -u); comm -3 <(printf %s "$old") <(printf %s "$new") | awk '{if (/^-/) r=r" "$1; else a=a" "$1} END {if (a!="") print "  new:" a; if (r!="") print "  removed:" r}'; old=$new; done
Run Code Online (Sandbox Code Playgroud)

...生成了以下列表:

1.18   1993-06-01
  new:  -e --expression -f --file -h --help
        -n --quiet --silent -V --version
2.05   1994-05-13
3.01   1998-07-23
  new: -r --rxtest
3.02   1998-08-02
4.0.6  2003-03-18
  new: -i --in-place -l --line-length
       -R --regexp-extended --regexp-perl
       -s --separate -u --unbuffered
  removed: --rxtest
4.0.7  2003-04-11
4.0.8  2003-10-21
4.0.9  2004-01-10
4.1    2004-06-15
  new: --posix
  removed: -h
4.1.1  2004-07-06
4.1.2  2004-08-22
4.1.3  2005-01-19
4.1.4  2005-01-28
4.1.5  2006-02-03
4.2    2009-04-30
  new: -b --binary -E --follow-symlinks
4.2.1  2009-06-27
4.2.2  2012-12-22
  new: --null-data -z --zero-terminated
4.3    2017-01-04
  new: --sandbox
4.4    2017-02-03
4.5    2018-03-31
4.6    2018-12-20
  new: --debug
  removed: -R --regexp-perl
4.7    2018-12-21
4.8    2020-01-14
Run Code Online (Sandbox Code Playgroud)

从那里我们可以看到,它-z首先出现在 2012-12-22 发布的 4.2.2 版本中。

注意编译前需要-R/--regexp-perl从4.0.6到4.5版本#define REG_PERL,所以Debian、Ubuntu等打包版本从来不支持这个选项。