我有下面的~/.gitconfig
[alias]
print = !printf %s\\\\n a b c它的作用如下:
$ git print
a
b
c但是现在我将它更改为下面的~/.gitconfig
[alias]
print = !printf %s\\\\n "a b" c然而,a和b仍在经历分词:
$ git print
a
b
c如果""引号没有阻止分字,那么它们在做什么呢?
这些命令是如何解析的?
发布于 2019-05-07 06:24:27
Git的配置语言解析器将双引号用于自己的目的
..。双引号
"和反斜杠可以通过将它们分别转义为\"和\\来包含。在读取时,删除其他字符前面的反斜杠;例如,\t作为t读取,\0作为0读取.
当这一段讨论分段名称时,双引号和双反斜杠规则也适用于分段名称之外。其余的引号在任何地方都适用,除了分段名称中的\t=t类型的东西:
在双引号中,双引号
"和反斜杠\字符必须转义:使用\"表示",使用\\表示\。 在\"和\\之外的转义序列是识别的:换行符(NL)的\n,水平制表的\t(HT,TAB)和背景色(BS)的\b。其他字符转义序列(包括八进制转义序列)无效。
请注意,所有这些都与别名无关:这些规则适用于.gitconfig或.git/config文件中的所有行。(这在子模块路径中很重要,尽管通常不会在一个子模块路径中编码双引号。)
现在,在完成配置解析器读取.git/config文件之后,如果该行位于alias部分,则定义别名。在这个别名中,双引号确实阻止了分字:
[alias]
foo = log \"a b\"
$ git foo
fatal: ambiguous argument 'a b': unknown revision or path not in the working tree.请注意,要通过配置解析器,首先必须给出这些配置解析器的反斜杠。为了避免这种特别的烦恼,我们可以用单引号代替:
[alias]
foo = log 'a b'产生同样的结果。
如果别名是shell别名(以!为前缀),则整个字符串(当然减去感叹号)将被输入shell。要观察这一点,请使用GIT_TRACE
[alias]
foo = !printf %s\\\\n 'a b'
$ GIT_TRACE=1 git foo
23:15:46.947801 git.c:670 trace: exec: git-foo
23:15:46.948153 run-command.c:643 trace: run_command: git-foo
23:15:46.948883 run-command.c:643 trace: run_command: 'printf %s\\n '\''a b'\'''
a b如果通过配置解析器获得双引号,它们具有相同的效果:
$ GIT_TRACE=1 git foo
23:16:24.919042 git.c:670 trace: exec: git-foo
23:16:24.919402 run-command.c:643 trace: run_command: git-foo
23:16:24.920114 run-command.c:643 trace: run_command: 'printf %s\\n "a b"'
a b当然,我们需要四个反斜杠的原因是,Git配置解析器将它们转换为两个反斜杠(如GIT_TRACE=1输出所示),而shell本身则将它们转换为一个反斜杠,printf与n组合起来生成一个换行符。
尝试化名:
foo = !printf %s\\\\n "a b在以下方面失败:
fatal: bad config line 30 in file [path]/.gitconfig因为Git本身正在运行它的逐行解析器,并且对未关闭的引号不满意。
https://stackoverflow.com/questions/56015130
复制相似问题