在脚本中强制使“git status”在终端上输出彩色

89

编辑:

我想提出一个建议,即解析颜色通常是一个不明智的想法。

我想这样做的部分原因是为了能够在自己的脚本输出中解析并传递它。这样做还可以,但使用模拟终端等重新构建带有颜色的部分可能更合理!

原始问题如下。


我喜欢看到颜色,因为我的脚本足够强大(到目前为止)可以处理颜色代码。我确实感觉自己与众不同,但老实说我真的不明白为什么在脚本中需要解析转义码之类的东西会成为大问题。如果颜色对交互使用有帮助,那么在聚合数据和处理比手动处理更多数据的脚本使用中,为什么它们不能帮助呢?难道颜色不是更加重要吗?

总之,我写了一个不错的小型shell脚本来搞定git status输出,而我只是想让这个脚本保持颜色不变。我的全局git配置设置为,在git状态中显示已更改和未跟踪的文件列表时以颜色显示。不幸的是,与git diff不同,我找不到强制git status显示颜色的选项。

为了非常清楚,请看下面的问题:

$ git status

产生完美的输出,但(以下是我的脚本摘录)

git status | sed "s/^#/\x1b[34m#[0m/"

不能产生有颜色的 git status 输出,可以从这里看出,我明确地将前导哈希字符转换为蓝色,因为它有助于突出显示来自我的脚本输出的不同区域。

有人知道如何使其输出彩色吗?也许有一个标准程序可以用作“虚拟终端”STDIN / STDOUT管道吗?事实上,我还在开发一个pty伪终端工具,所以我肯定可以利用它来实现此目的,但这是一种相当笨重的解决方案(而且由于我尚未完成构建,因此尚未准备好使用)。


还可以参考 如何为 Git 输出着色 - Sithsu
7
在脚本中解析颜色代码以提取有意义的数据存在一个问题,那就是不同的用户可能已经在他们的配置文件中设置了不同的颜色。为了避免这种情况带来的问题,Git 提供了各种命令的 --porcelain 选项,该选项提供了一种易于解析且在不同环境中更不易发生变化的格式。 - joeytwiddle
1
补充@joeytwiddle的评论,作为设计注意事项,仅将状态信息编码为颜色是一个不好的想法,因为有些人有各种类型的色盲(红绿色盲最常见,但还有蓝黄色盲等等;有关详细信息,请参见https://nei.nih.gov/health/color_blindness/facts_about)。它影响大约10%的人类!始终确保除了纯粹的颜色之外,还有其他提取必要信息的方法。 - torek
3个回答

150

为了避免更改git配置,您可以通过传递带有-c的配置变量来仅为当前命令启用颜色。

对于status命令,该变量是color.status

    git -c color.status=always status | less -REX

diffshowloggrep命令的变量名为color.ui

    git -c color.ui=always diff | less -REX

请注意,在使用statusdiff参数之前必须使用-c,而不是在其之后。
另外,对于diffshowloggrep命令,您可以在命令之后使用--color=always选项。
    git diff --color=always | less -REX

注意:正如Steven所说,如果您想提取有意义的数据,那么可以使用--porcelain获得更适合解析的输出,而不是解析颜色来提取含义。
    git status --porcelain | awk ...

如果需要,稍后可以重新添加颜色。

要获取用户配置的颜色,可以使用git config --get-colour命令:

    reset_color="$(tput sgr0)"
    remote_branch_color="$(git config --get-color color.branch.remote white)"

    echo "Pushing to ${remote_branch_color}${branch_name}${reset_color}"

这里有更多的例子


2
你说这个对于日志(log)可行,但我发现并非如此。:( - Adrian
3
嗯,看起来对于 log 命令有所不同,命令是 git log --color=always。关于命令行界面的不一致性有点遗憾。 - Adrian
2
看起来git试图将此与diffshowlog统一起来,在命令后使用--color=...开关,但没有更新status - Adrian
2
我发布了这个问题;在我的代码中解析git status的部分,它们解析git status --porcelain的输出。尽管如此,知道我们可以使用-c覆盖当前调用的git配置仍然非常酷。 - Steven Lu
2
git -c color.ui=always status 在 git 版本 2.20.1 中有效,无需使用另一个变量 color.status - ks1322
显示剩余5条评论

24

编辑:

我强烈建议不要解析颜色,因为这是一个普遍的错误想法。

我需要解析颜色并将其传递到自己的脚本输出中。虽然这样可以实现,但最好使用porcelain或其他工具重新构建着色部分!

下面是原始答案。


我发现在提问后很快就能找到答案。这可能与思考问题并将其写出有关,你会想出更好的解决方案。无论如何,解决此问题的方法只是:

git config color.status always

我想一个通用的解决方案涉及使用expect或与pty相关的内容,以强制任何需要它的程序认为它们在终端上。

7
@joeytwiddle给出了更好的答案……始终强制指定颜色意味着你可能会在一些不想要的地方得到颜色。使用-c选项可以将作用范围限制在正在运行的脚本中。 - danwyand
4
git config --global color.ui auto - Ashish Sajwan
1
我更改了我的接受方式,它更直接地回答了我的问题。@AshishSajwan 将颜色设置为自动意味着在使用脚本运行时不会产生颜色。 - Steven Lu
是的,输出通常要么是人类可读的,要么是机器可读的,并且它们具有非常不同的属性。 - Raúl Salinas-Monteagudo
1
如果您选择解析瓷质数据并将自己的颜色代码添加到输出中,您可以检查用户是否已为某些内容配置了首选颜色,例如:current_branch_termcode="$(git config --get-color color.branch.current green)",其中 green 是您想要使用的后备方案,如果没有找到自定义配置,则最好将 git 的默认颜色放在那里。 - joeytwiddle

2

当我使用执行shell命令的git别名时,遇到了同样的问题。显然,git shell不会继承当前环境,因此它对我的着色设置一无所知。

除了添加全局git color ui设置外,我通过使我的别名如下所示来解决了这个问题,其次要告诉使用颜色的次要命令,因为默认情况下,人们提到的1.8.x版本已经支持git。

[alias]
  ignored = !git ls-files -v|grep --color '^h'

这现在产生了等效的带颜色输出,当作为别名运行时与我刚刚运行命令时一样。
对于sed,这个答案似乎更可靠,使用tput。 https://unix.stackexchange.com/a/45954

1
虽然这个链接可能回答了问题,但最好在此处包含答案的基本部分并提供参考链接。仅有链接的答案如果链接页面发生更改可能会变得无效。 - ZygD

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接