因此,自从 GitHub 删除了非高级帐户的洞察选项卡后,我便尝试每天在本地列出我的 git 存储库中的插入和删除内容。
我想出了这种打印我想要的内容的方法:
git log --pretty="@%ad" --date=short --shortstat | tr "\n" " " | tr "@" "\n"
这会产生这种输出:
2024-06-13 7 files changed, 400 insertions(+), 406 deletions(-)
2024-06-12 3 files changed, 145 insertions(+)
2024-06-12 5 files changed, 638 deletions(-)
2024-06-12 1 file changed, 1 insertion(+), 1 deletion(-)
注意文件、插入和删除中的复数形式。另一个问题是提交可能没有插入或删除(或两者兼有,但我们忽略这种情况)。
我已经快完成了,我只需要提取日期、插入和删除并按日期分组。这将生成某种“每天完成的工作”图表。
我制作了这个正则表达式来捕获处理所有可选项的字段:
/^([0-9]{4}-[0-9]{2}-[0-9]{2})\s{3}[0-9]+\sfile(s)?\schanged,\s(([0-9]+)\sinsertion(s)?\(\+\))?(,\s)?(([0-9]+)\sdeletion(s)?\(\-\))?\s$/gm
现在我需要获取第 1、第 4 和第 8 组,例如sed
:
echo "2024-06-13 7 files changed, 400 insertions(+), 406 deletions(-) " |
sed -r 's/^([0-9]{4}-[0-9]{2}-[0-9]{2})\s{3}[0-9]+\sfile(s)?\schanged,\s(([0-9]+)\sinsertion(s)?\(\+\))?(,\s)?(([0-9]+)\sdeletion(s)?\(\-\))?\s$/\1 \4 \8/gm'
这样就能产生正确的输出:
2024-06-13 400 406
但是如果输入字符串没有插入或删除,sed 就不会为该捕获组打印任何内容。例如:
2024-06-13 400
我无法判断单个数字是插入还是删除。
有没有办法从每一行中提取组,但如果组不存在则打印“0”作为占位符?(不一定单独使用 sed,也不一定在单个命令中)。
总是有很多解决方案。下面是其中一种。我喜欢用一个正则表达式来完成所有事情,但有时最好保持简单并逐步完成:
这会匹配日期,然后在行尾添加占位符字符串“
XXX C0 I0 D0
”。接下来的 3 条命令会将相应的内容替换0
为实际更改、插入或删除的项目数。从日期末尾到占位符的整行内容将被删除,C、D 和 I 字母将被删除,只留下附加在其上的更新数字。如果中间的占位符为空,则会出现双倍空格,可以用零填充。同样,如果没有最后一个项目,则行将以空格结尾。
--numstat
如果您自己使用并计算所需的统计数据,可能会更可靠。使用--numstat
(例如,在git log --numstat --pretty="@%ad" --date=short
)会产生如下输出:然后您可以使用类似以下 awk 代码:
示例输出:
如果您想要合并同一天所有提交的统计信息,则可以使用以下命令:
所以:
0 insertions
如果缺少“changed”,我们可以在后面插入:0 deletions
类似地,如果有必要,我们可以附加:完整脚本
将输出通过管道传输
git log --pretty=%as --shortstat
到这个小程序中(不需要@
格式或tr
命令):在每个 Unix 机器上的任何 shell 中,使用对任何 awk 的一次调用,这
将产生以下输出:
以下是上述脚本的注释版本,有助于解释其功能:
不过,从你的回答中我看到你实际上想要对每个日期的值求和 - 如果是这样,那么再次使用 any
awk
:将产生以下输出:
而不必一次将所有值存储在内存中。
以上内容假设如下:
产生如下输出:
基于@meuh 的正则表达式的完整解决方案,但忽略了更改的文件的数量:
tail
需要第二行中的命令来删除第一行中替换引入的第一个空行tr
。此后,该
sed
命令将删除除日期、插入行和删除行之外的所有内容,并考虑没有插入或删除的提交。然后,该
awk
命令将第二列和第三列相加,并按第一列(日期)分组。但由于awk
数组键没有排序,我们需要按sort
第一列对结果进行最终排序,这将生成按日期降序排列的唯一每日统计数据列表,例如:在 Perl 中,这相对简单,因为您可以使用整数格式,将空值打印
%d
为零printf
,也可以使用//
运算符设置“默认”值:或者使用
s///e
,它允许在替换部分使用 Perl 代码:不过,正如 muru 已经提到的,的输出
--numstat
可能更容易解析。另一方面,单独选择每个值可能更容易,这将有助于避免使用复杂的正则表达式。例如,像这样同时进行每日汇总:
顺便说一句,这很容易调整,因此
tr
不需要,只需设置@
为记录分隔符:(请注意,正则
\s
表达式中的是 Perl-ism。虽然 GNU 出于某种原因支持它,但它是非标准的,并且不受其他系统上的标准工具支持。)