最后的解决方案

最后的解决方案

grep我在 zsh 中有一个函数,用于在 的输出上运行git log,以突出显示包含提交的哈希、作者、消息等的行。我正在重写以尝试为输出添加颜色,并希望防止 grep 覆盖传递的前景色。
我尝试了 的所有变体--color=(always|never|auto)。这是我目前坚持使用的命令:

# raw command:
unbuffer git log --pretty=$'%C(bold blue)%h%C(reset) \t%C(bold cyan)%aD%C(reset)\t%C(dim white)\t%an%C(reset)\t%C(white)%s%C(reset)' | grep -i '.*'update'.*' | column -t -s $'\t'

# w/ comments:
unbuffer # From `expect` apt package, preserves color across piping by pushing to a buffer? idk.

# git log, formatted
git log --pretty=$'%C(bold blue)%h%C(reset) \t%C(bold cyan)%aD%C(reset)\t%C(dim white)\t%an%C(reset)\t%C(white)%s%C(reset)'

grep -i '.*'update'.*' # grep `update` from any line in input, hardcoded here but could also be a parameter

column -t -s $'\t' # tabulate

输出如下所示。

输出如下

此外,column不使用 而通过管道将输出制成表格unbuffer也会冲淡颜色,并且没有--color=never命令选项column。使用unbuffer还会导致grep的着色完全不起作用。

我想要的只是让 grep 匹配的背景突出显示为红色、绿色或任何颜色,同时保留图像中所见的文本颜色,即红底绿色、红底蓝色等。我不完全熟悉终端在后台如何工作以及为什么在管道时会丢失颜色。

我确信我可以编写一个 C++ 程序来完成所有这些操作,方法是在必要时插入 ANSI 颜色代码,但我想我至少会问一下。我确实只想使用可以通过安装的命令,apt因为这是我的整个终端配置的一部分,我通过 git repo 在多个设备上同步它。

对此点进行编辑:

  • 我最初尝试添加一个-A1 -B1标志来grep显示前后的提交,因此希望明确突出显示。
  • 答案来自@丹尼尔-t可以解决丢失颜色的问题git log,但无法grep突出显示匹配项。

我可以手动将颜色代码写入字符串并通过 回显 来实现所需的效果echo "\e[1;34m13ca348\e[m \e[1;36mSun, 29 Jan\e[m -- \e[1;41m\e[1;32mCommit message\e[m"。此输出正是我想要的(请注意,绿色和红色包裹了前景色和背景色代码),但我怀疑终端程序是否以这种方式构造颜色,所以我不知道其他程序是否能够以这种方式轻松地将它们组合在一起。

答案1

所以我找到了一个解决方案。通过设置GREP_COLORSgrep调用的内联,我可以将 grep 更改为仅突出显示背景,而不会与 的前景颜色冲突git log。我还必须传递--color=alwaysgrep防止在管道传输时发生清洗column,如下所示:GREP_COLORS="ms=41" grep -i update --color=always

看:https://askubuntu.com/a/1485711/1764786GREP_COLORS占位符表格

另一个问题column是,它不支持每个 ANSI 颜色转义,最终会清除它不喜欢的任何颜色。我的解决方法是使用column_ansi并且其主要作用是作为替代品。

就像我在编辑中所说的那样,我试图包含标志-A1 -B1grep获取前后的提交。

这是我最终使用的完整命令,我最终将其包装在一个函数中:

glgrep() {
    git log --color=always --pretty=format:$'%C(bold blue)%h%C(reset)\t%C(bold cyan)%aD%C(reset)\t%C(dim white)\t%an%C(reset)\t%C(white)%s%C(reset)' | GREP_COLORS="ms=41" grep -i $1 --color=always -A1 -B1 | column_ansi -t -s $'\t' | sed 's/^[ \t]*//;s/[ \t]*$//'
    # call after `column_ansi` requires trimming. i dont know why (extra following newline char?)
}

答案2

最后的解决方案

尝试git log --color --pretty="$(printf '\e[1;34m%%h \e[36m%%aD\e[35G\e[;2;37m\t%%an\e[70G\e[;37m%%s\e[m')" | GREP_COLORS='ms=1;32;41:sl=37' grep -Pi '\e\[;37m.*\K''update' --color=always。我不再使用columnsed。 new\e[70G只会将光标移动到第 70 列,这对于名称来说应该足够了。前两列或多或少是固定长度的,不需要太多。

最后的解决方案

简单的解决方案

尝试一下git log --pretty=$'%C(bold blue)%h%C(reset) \t%C(bold cyan)%aD%C(reset)\t%C(dim white)\t%an%C(reset)\t%C(bold green red)%s%C(reset)' --color=always | grep -i '.*'update'.*' | column -t -s $'\t'。我刚刚将最后的“白色”改为“粗体绿色红色”。

突出显示整个提交消息

根据您想要突出显示整个提交消息的颜色代码示例,很容易为整个最后一列着色。无需将两个命令的颜色组合在一起。我不知道您使用的哪个版本的 grep 以红色为背景,但 Ubuntu 上的 grep 以红色为前景,所以我们需要覆盖它。

高级解决方案

编辑:根据你想要的:

命令变成git log --pretty=$'%C(bold blue)%h%C(reset) \t%C(bold cyan)%aD%C(reset)\t%C(dim white)\t%an%C(reset)\t%C(white)%s%C(reset)' --color=always | GREP_COLORS='ms=1;41;32:sl=37' grep -Pi '\e\[37m.*\K''update' --color=always | column -t -s $'\t'。编辑'update'部分以选择要搜索的模式。

仅突出显示匹配的部分

环境GREP_COLORS变量控制 grep 如何突出显示和以:.分隔ms=1;32;41,分别在红色上应用粗体绿色。 grep 将在之后立即重置颜色,因此我们需要添加sl=37以恢复白色(在 xterm 上是必需的,但在大多数终端上不是,例如 Konsole)。如果省略,ANSI 颜色转义序列通常会与之前的前景、背景或样式合并,但您无法推送/弹出/撤消,因此这不适用于您的情况。然后我匹配\e\[37m(需要-P)以限制我们提交消息(以避免在其他地方匹配时出现故障颜色),依赖于我们只在 git 中使用白色的事实。然后告诉.*\Kgrep 在您的之后搜索您的关键字,并避免突出显示和破坏之前的颜色代码本身。最后我们需要--color=always启用我们的新颜色。

顺便说一句,你不需要经常使用 reset。这是一个较短的版本git log --color --pretty=$'%C(bold blue)%h \t%C(cyan)%aD\t%C(reset dim white)\t%an\t%C(reset white)%s%C(reset)' | GREP_COLORS='ms=1;32;41:sl=37' grep -Pi '\e\[;37m.*\K''update' --color=always | column -t -s $'\t'。中间的几个仍然保留,因为它们比 no-dim 更可靠(输出的颜色代码与 no-bold 相同),最后一个只有在你没有彩色 bash 提示符时才需要。

旧答案

您需要传递--color=alwaysgit,而不是grepcolumn。尝试git log --pretty=$'%C(bold blue)%h%C(reset) \t%C(bold cyan)%aD%C(reset)\t%C(dim white)\t%an%C(reset)\t%C(white)%s%C(reset)' --color=always | grep -i '.*'update'.*' | column -t -s $'\t'

我得到以下输出:

home@daniel-tablet1:~/WebstormProjects/linuxenv$ git log --pretty=$'%C(bold blue)%h%C(reset) \t%C(bold cyan)%aD%C(reset)\t%C(dim white)\t%an%C(reset)\t%C(white)%s%C(reset)' --color=always | grep -i '.*'update'.*' | column -t -s $'\t'
13ca348   Sun, 29 Jan 2023 15:56:02 -0500    Daniel Tang  Update PlantUML 1.2022.6 -> 1.2023.0
83b31a2   Sun, 29 Jan 2023 15:48:21 -0500    Daniel Tang  Update Gradle 7.5.1 -> 7.6
85f2b04   Sun, 29 Jan 2023 15:45:28 -0500    Daniel Tang  Update GraalVM 22.3.0 -> 22.3.1
5e86df9   Sun, 29 Jan 2023 15:39:59 -0500    Daniel Tang  Update JetBrainsMono 2.242 -> 2.304
7e984d4   Wed, 26 Oct 2022 18:21:23 -0400    Daniel Tang  Update graalvm 22.3
ee202a6   Wed, 12 Oct 2022 10:00:33 -0400    Daniel Tang  Update rustup settings.toml hash
6a0c58f   Mon, 19 Sep 2022 23:54:54 -0400    Daniel Tang  Update
a9755a3   Tue, 23 Mar 2021 13:54:27 -0400    Daniel Tang  Fix nvmupdate
e936dab   Fri, 19 Mar 2021 17:29:32 -0400    Daniel Tang  Update
0b8e7e3   Wed, 17 Mar 2021 04:19:11 -0400    Daniel Tang  Update
(sky blue)(turquoise                    )    (dark grey)  (white) (konsole)
(RGB blue)(cyan                         )    (dark grey)  (light gray) (xterm)
(navyblue)(aquamarine                   )    (dark grey)  (light gray) (gnome-terminal)

我删除了它,unbuffer因为它不仅需要安装,而且还会导致命令挂起在我的计算机上。您想要的标准命令是stdbuf -o0。如果您说那unbuffer是在修复颜色,那一定是因为它通过分配 PTY 假装是终端。如果我们使用更有效的直接解决方案,那就没有必要了--color=always

如果您想要找出哪个命令无法传递颜色,可以使用catgit log --pretty=$'%C(bold blue)%h%C(reset) \t%C(bold cyan)%aD%C(reset)\t%C(dim white)\t%an%C(reset)\t%C(white)%s%C(reset)' | cat会导致缺少颜色,而没有 则会cat出现分页和颜色。 这表明git无法发出 ANSI 颜色代码。 即使您编写了 C++ 程序,那些也是您自己的颜色代码,没有来自 的颜色代码git

不必担心grep覆盖颜色代码。您的.*'update'.*转到行首。颜色代码是带有转义序列的特殊选择的文本。即使 grep 附加了任何颜色代码,它也会git立即被 的颜色代码覆盖。head -n1的输出是git --color=always。在这种情况下,没有决定插入颜色代码是件\e[1;34m9a8c818\e[m \t\e[1;36mMon好事,因为它是管道传输到某个东西,即之后,但即使您给出了,它只会在颜色代码前面加上它。我得到了。它在视觉上看起来是一样的,因为的颜色立即被之前的颜色覆盖。grepcolumngrep --color=always\e[01;31m\e[K\e[1;34m13ca348\e[m \t\e[1;36mSun, 29 Jangrepgit

相关内容