我一直在写带参数的 git 别名。我见过一些人用
[alias]
shAlias = !sh -c \" ... \"
和其他运行功能
[alias]
fAlias = "!f() { ... ; }; f"
似乎(一旦我开始使用 Bash ——这还不是我现在的位置)我认为做的任何事情都可以用任何一种形式来实现。
在什么情况下一种优于另一种?
除了可行性之外,是否存在处理差异?内存使用/速度/等?
TL;DR:对最简单的命令使用函数方法,一旦遇到任何引用问题,就切换到外部脚本。只是一起避免sh -c
。
我们可以看看 git 源码。它以特定方式解析引号,git
如果结果没有 shell 元字符(包括空格),则作为文件执行,execlp("sh", "-c", "result \"$@\"", "result \"$@\"", args...)
否则执行等价的操作。
基于此,创建别名的最佳方法肯定是创建外部脚本并使用:
[alias]
myAlias = !/path/to/script
它需要一个外部文件,但在所有其他方面它更好:
bash
按照您的要求运行代码,而其他形式只允许您运行sh
代码(区别就像 C++ 与 C)。git
将execve
您的可执行文件直接。git
知识。这只是一个脚本。根据您的建议,亚军是:
[alias]
fAlias = "!f() { ... ; }; f"
这不那么令人敬畏,因为:
sh
,因此不能使用任何bash
功能。git
引号需要一些特定的转义。git
' 的转义,但通常可以在不确切知道它如何执行命令的情况下通过,因为您只会使用函数的参数。最后一个是迄今为止最糟糕的:
[alias]
shAlias = !sh -c \" ... \"
这很糟糕,因为:
sh
.git
需要转义,也需要额外的sh
转义级别。sh
,如何使用 进行双重转义,以及如果有其他参数,git
如何git
附加到您的命令,并将其他参数传递为, 。"$@"
$1
$2
为了演示实际差异,假设您想为此命令创建一个别名,以通过以下方式获取远程服务器上的路径ssh
:
ssh "$1" 'echo "$PATH"'
您可以将其逐字复制粘贴到文件中,添加 shebang,然后使用:
[alias]
get-remote-path = !/path/to/my/script
或者您可以添加一些git
转义并使用函数方法:
[alias]
get-remote-path = "!f() { ssh \"$1\" 'echo \"$PATH\"'; }; f"
或者我们可以用这种方法费力地逃脱并再次逃脱sh -c
(不,没有最后一句话它是行不通的):
[alias]
get-remote-path = !sh -c 'ssh \"$1\" '\\''echo \"$PATH\"'\\' cthulhu
显然,最好使用脚本,或者在最坏的情况下使用函数方法,直到您需要可以轻松引用的更复杂的命令。
如果适用,请首选该函数,因为它由执行别名的任何 shell 直接执行。使用sh -c '...'
导致另一个进程启动。