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_COLORS
与grep
调用的内联,我可以将 grep 更改为仅突出显示背景,而不会与 的前景颜色冲突git log
。我还必须传递--color=always
以grep
防止在管道传输时发生清洗column
,如下所示:GREP_COLORS="ms=41" grep -i update --color=always
看:https://askubuntu.com/a/1485711/1764786
GREP_COLORS
占位符表格
另一个问题column
是,它不支持每个 ANSI 颜色转义,最终会清除它不喜欢的任何颜色。我的解决方法是使用column_ansi
并且其主要作用是作为替代品。
就像我在编辑中所说的那样,我试图包含标志-A1 -B1
以grep
获取前后的提交。
这是我最终使用的完整命令,我最终将其包装在一个函数中:
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
。我不再使用column
和sed
。 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 中使用白色的事实。然后告诉.*\K
grep 在您的之后搜索您的关键字,并避免突出显示和破坏之前的颜色代码本身。最后我们需要--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=always
到git
,而不是grep
或column
。尝试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
。
如果您想要找出哪个命令无法传递颜色,可以使用cat
。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)' | cat
会导致缺少颜色,而没有 则会cat
出现分页和颜色。 这表明git
无法发出 ANSI 颜色代码。 即使您编写了 C++ 程序,那些也是您自己的颜色代码,没有来自 的颜色代码git
。
不必担心grep
覆盖颜色代码。您的.*'update'.*
转到行首。颜色代码是带有转义序列的特殊选择的文本。即使 grep 附加了任何颜色代码,它也会git
立即被 的颜色代码覆盖。head -n1
的输出是git --color=always
。在这种情况下,没有决定插入颜色代码是件\e[1;34m9a8c818\e[m \t\e[1;36mMon
好事,因为它是管道传输到某个东西,即之后,但即使您给出了,它只会在颜色代码前面加上它。我得到了。它在视觉上看起来是一样的,因为的颜色立即被之前的颜色覆盖。grep
column
grep
--color=always
\e[01;31m\e[K\e[1;34m13ca348\e[m \t\e[1;36mSun, 29 Jan
grep
git