【问题标题】:read loop from <(git log --oneline) has different output from "git log --oneline" at terminal<(git log --oneline) 的读取循环与终端的“git log --oneline”输出不同
【发布时间】:2018-05-08 22:11:27
【问题描述】:

我遇到了一个奇怪的问题。我正在尝试解析 git 命令的输出。当我从命令行运行 git 命令时,它按预期工作:

$ git log --oneline 32004f
32004f9 (tag: This_is_a_tag,_too, tag: Tag_from_command_line, origin/Project_A, Project_A) Merged
65f6f61 More changes
925f619 (tag: This_is_a_tag) Pulled from remote
(etc.)

但一旦我尝试重定向或管道输出,括号内的任何内容都会消失:

$ while read -r ; do echo $REPLY; done < <(git log --oneline 32004f)
32004f9 Merged
65f6f61 More changes
925f619 Pulled from remote

[编辑:请注意,echo 命令严格用于说明问题。实际脚本会将结果拆分成多个变量进行解析处理]

$ git log --oneline 32004f | hexdump -C | head
00000000  33 32 30 30 34 66 39 20  4d 65 72 67 65 64 0a 36  |32004f9 Merged.6|
00000010  35 66 36 66 36 31 20 4d  6f 72 65 20 63 68 61 6e  |5f6f61 More chan|
00000020  67 65 73 0a 39 32 35 66  36 31 39 20 50 75 6c 6c  |ges.925f619 Pull|
00000030  65 64 20 66 72 6f 6d 20  72 65 6d 6f 74 65 0a 64  |ed from remote.d|

但是我创建的一个快速的 shell 脚本回显括号可以正常工作:

$ cat test.sh
#!/bin/bash
echo "32004f9  (HEAD -> Project_A, tag: This_is_a_tag,_too, tag: Tag_from_command_line, origin /Project_A) Merged"

$ while read -r ; do echo $REPLY; done < <(./test.sh)
32004f9 (HEAD -> Project_A, tag: This_is_a_tag,_too, tag: Tag_from_command_line, origin /Project_A) Merged

我被难住了。谁能帮我解决这个问题?

Bash 版本:GNU bash,版本 4.4.12(3)-release (i686-pc-cygwin) git版本:git版本2.15.0

【问题讨论】:

  • echo $REPLY 创建了一堆额外的错误。总是引用:echo "$REPLY";见BashPitfalls #14
  • 也就是说,要查看您的行为是否与输出到 TTY 的行为不同,只需通过管道发送到 cat:如果 foo | catfoo 的不同之处与您正在调查的方式相同,您知道这是基于 isatty() 的行为,正如 randomir 的回答所表明的那样。
  • (顺便说一句,“失败”不是一个描述性很强的词,在一个网站的上下文中,几乎每个问题都是关于以非预期方式表现的事情;我已尝试进行编辑以使标题更具体地针对单个问题)。

标签: git bash cygwin parentheses


【解决方案1】:

检查--decorate 选项以获取git log

--no-decorate, --decorate[=short|full|auto|no]

打印显示的任何提交的引用名称。如果指定了short,则不会打印引用名称前缀refs/heads/refs/tags/refs/remotes/。如果指定了full,将打印完整的引用名称(包括前缀)。如果指定了 auto,则如果输出将发送到终端,则显示的 ref 名称就像给出了 short 一样,否则不显示任何 ref 名称。默认选项是short

看起来您在 git 配置中的某处设置了 --decorate=auto

要强制引用名称(包括标签),只需指定:

git log --oneline 32004f --decorate=short

【讨论】:

  • 感谢您的提示。我以前从来没有遇到过一个程序,其输出取决于它是去终端还是被管道/重定向。这将对我编写 Bash 脚本的方式产生重大影响——我总是使用命令行来对命令进行原型设计,然后将其复制并粘贴到我的脚本中(有时在获得正确的反斜杠数量时会有不同程度的挫败感) .
  • 不客气。这很容易被忽略,但许多命令行/UNIX 工具在写入终端 (TTY) 时与写入文件时的输出格式实际上是不同的。通常,写入文件时会省略 ANSI 代码(如颜色)——lsgrepgit show/diff/log 默认情况下都会这样做。许多人可以选择控制它(--color 或类似的)——试试:ls --color=always | hd。正如上面 CharlesDuffy 所说,C 程序使用 isatty(fd) 来区分,而您可以在 Bash 中使用 [ -t fd ]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-09-18
  • 2021-10-26
  • 1970-01-01
  • 2022-11-16
  • 1970-01-01
  • 2018-08-08
  • 2020-12-11
相关资源
最近更新 更多