原来的答案,这不起作用,所以转到工作版本的编辑
sed
如果直接从命令行使用,以下解决方案对我有用。它不使用任何临时字符串来切换\
并/
依赖于sed
sy
命令。
$ git --no-pager log --all --graph --decorate --oneline --color=always | tac | sed 'h
s!\( *[0-9a-z]\{7\} .*\)\{0,1\}$!\1!
y/\\\/_¯/\/\\¯_/
x
s!\(.*\)\( *[0-9a-z]\{7\} .*\)\{0,1\}$!\2!
x
G
s/\n//' | less -X +G -r
它假定 SHA 代码长度为 7 个字符,并使用它来“识别”什么不是\
, , , , 和 的前导序列,/
我|
无法_
将*
其放在<space>
第一个s
命令的搜索模式的开头并到位.
在第二个s
命令中的第一个。
sed
我不知道为什么当所有命令都放在使用sed
s-f
选项调用的脚本中时,我无法让它工作。
编辑(上面的代码实际上是错误的)
正如@user1902689 所指出的那样,sed
脚本可以让任何人(包括我自己)的眼睛流血,因为它们非常神秘。
在我看来,如果不使用 ,任务将很容易完成--color=always
,在这种情况下,输出的文本git log
将与我们在屏幕上看到的相同;--color=always
相反,使用插入控制序列,如^[[33m
散布在文本中以控制着色(不同分支的不同颜色,...)。
但是有一个彩色输出很好,所以我将输出定向git log --color=always ...
到文件,并查看它,发现哈希总是出现在和之间^[[33m
,^[[m
其中^[
单个字符可以通过点击Ctrl+获得V,然后Esc。这些本质上是 bash 解释为将颜色分别设置为黄色和变回白色的转义序列(链接)。
哈希值,它不是该行中唯一的 7 个字母数字字符串(例如 thiswrd
,可以在提交主消息中),几乎可以肯定是第一个,因此可以安全地使用贪婪表达式(sed
没有非贪婪表达式)在它之后,而不是之前(.*
哈希匹配正则表达式之前的 a 将使该正则表达式匹配该行上的最后一个 7 字母数字字符串,anytext
例如,该字符串可能是 ,并且哈希将丢失在某处.*
)。为了允许以.*
不吞噬散列的方式使用贪婪,我们可以将散列括在与 in不匹配的换行符\n
之间.
.*
(因此,它们必须显式键入)使用s
命令,以便我们可以通过在搜索模式中显式使用 some来“限制”.*
连续命令中的贪婪。s
\n
我认为以下代码(稍后解释)不是确定的,因为它对用于获取彩色哈希字符串的着色转义序列进行硬编码,但只要我尝试过,它就可以工作。
$ git --no-pager log --all --graph --decorate --oneline --color=always | tac | sed '
s/\(\(^[\[33m\)\([0-9a-z]\{7\}\)\(^[\[m\)\(.*\)\)/\2\n\3\n\4\5/
h
s/^.*\(\n[a-z0-9]\{7\}\n.*\|$\)/\1/
x
s/\n[a-z0-9]\{7\}\n.*$//
y/\\\/_¯/\/\\¯_/
G
s/\n\([a-z0-9]\{7\}\)\n/\1/
s/\n//' | less -X +G -r
每行包含三个部分Graph OpeningColorTagHashClosingColorTag Message
,或仅包含第一部分Graph
。该sed
字符串由 9 个命令组成,这些命令执行我打算对原始答案执行的操作,但方式有所不同(特别是某些命令的顺序颠倒了,以保存x
命令)。
- 第一个命令在字符串的每一侧
s
放置一个换行符(如果该行中没有散列,则不执行任何操作;请注意,合并/分歧之前/之后的行后面没有散列或消息)。这有“隔离”的目的。请注意,捕获组是根据开始标记的出现顺序编号的,因此在替换字符串中:†</sup>
\n
Hash
[0-9a-z]\{7\}
Hash
\(...\)
\(
\2\n\3\n\4\5
\2
指的是^[\[33m
,它是OpeningColorTag
(注意:是通过点击+^[
获得的单个字符,然后,而“true”必须用反斜杠转义);CtrlVEsc[
\
\3
指Hash
,[0-9a-z]\{7\}
\4
指ClosingColorTag
, ^[\[m
(这里所说的 for\2
也成立);
\5
是接下来的任何内容,.*
(隐含到行尾)。
现在模式空间(当前行,正如我们目前所编辑的那样)包含原始行,在哈希 ( ) 的每一侧都有两个嵌入的换行符Graph OpeningColorTag\nHash\nClosingColorTag Message
,或者如果它不包含哈希 ( ),则为未修改的原始行Graph
。
- 该
h
命令将模式空间“保存”到保持空间中(将其视为抽屉)。
现在模式和保持空间具有相同的内容(Graph OpeningColorTag\nHash\nClosingColorTag Message
或Graph
)。
- 第二个
s
命令仅捕获和替换自身 ( /\1/
) 并丢弃之前的所有内容 ( ^.*
, ie Graph OpeningColorTag
),或者 (\|
在捕获组中分隔替代项\(...\)
)
- 换行符封闭的散列及其后面的所有内容(即提交主消息)
\n[a-z0-9]\{7\}\n.*
,
- 或行尾
$
,
现在模式空间包含\nHash\nClosingColorTag Message
,如果没有散列,则为空字符串。
- 该
x
命令交换模式和保持空间的内容,使多行\nHash\nClosingColorTag Message
(或空字符串)保存在保持空间中,多行在Graph OpeningColorTag\nHash\nClosingColorTag Message
模式空间中,准备重新编辑。
- 第三个
s
命令命令\nHash
从模式空间中去除 , 以及它后面的所有内容。
现在模式空间包含Graph OpeningColorTag
.
- 将
y
前两个 non-escaped 之间的每个字符替换/
为第二个和第三个 non-escaped 之间的对应字符/
。这里反斜杠和正斜杠都必须用反斜杠转义。(这应该是安全的,因为OpeningColorTag
不应包含任何已翻译的字符。)
现在模式空间包含Hparg OpeningColorTag
,其中Hparg
是Graph
(或Hparg
仅)的“反转”版本。
- 该
G
命令获取保持空间的内容并将其附加到(因此大写G
;小写g
将复制到而不是附加到)模式空间中,中间有一个换行符\n
。
现在模式空间包含Hparg OpeningColorTag\n\nHash\nClosingColorTag Message
(或Hparg\n
仅),从现在开始我们不再关心保持空间。
- 第四个
s
命令捕获该\nHash\n
部分并将其替换为Hash
.
现在模式空间包含Hparg OpeningColorTag\nHashClosingColorTag Message
or Hparg\n
。
- 最后一个
s
命令删除剩余的换行符\n
。
最后,模式空间包含Hparg OpeningColorTagHashClosingColorTag Message
or Hparg
。
步骤 8. 和 9. 不能融合在一起(例如 s/\n\n\([a-z0-9]\{7\}\)\n/\1/
),因为\n
只有当行包含哈希时,包含哈希的两个才存在(s
如果没有哈希,第 1 点的第一个不执行任何操作),而第一个\n
始终存在,因为它带有G
命令。
†</sup> 实际上,最外部的组\(
...\)
是不需要的(确实没有使用),因此可以将其删除,并且对其他捕获组的所有数字引用都可以减 1,例如 s/\(\(^[\[33m\)\([0-9a-z]\{7\}\)\(^[\[m\)\(.*\)\)/\2\n\3\n\4\5/
可以更改为s/\(^[\[33m\)\([0-9a-z]\{7\}\)\(^[\[m\)\(.*\)/\1\n\2\n\3\4/
; 但我会在答案中保留不必要的组,因为它有机会提及不那么广为人知的捕获组编号。