5

我一直在写带参数的 git 别名。我见过一些人用

[alias]
  shAlias = !sh -c \" ... \"

和其他运行功能

[alias]
  fAlias = "!f() { ... ; }; f"

似乎(一旦我开始使用 Bash ——这还不是我现在的位置)我认为做的任何事情都可以用任何一种形式来实现。

在什么情况下一种优于另一种?

除了可行性之外,是否存在处理差异?内存使用/速度/等?

4

2 回答 2

8

TL;DR:对最简单的命令使用函数方法,一旦遇到任何引用问题,就切换到外部脚本。只是一起避免sh -c


我们可以看看 git 源码。它以特定方式解析引号,git如果结果没有 shell 元字符(包括空格),则作为文件执行,execlp("sh", "-c", "result \"$@\"", "result \"$@\"", args...)否则执行等价的操作。

基于此,创建别名的最佳方法肯定是创建外部脚本并使用:

[alias]
 myAlias = !/path/to/script

它需要一个外部文件,但在所有其他方面它更好:

  • 您可以使用任何您想要的解释器运行。您甚至可以bash按照您的要求运行代码,而其他形式只允许您运行sh代码(区别就像 C++ 与 C)。
  • 除非您愿意,否则不会启动额外的 shell。gitexecve您的可执行文件直接。
  • 不需要转义。这只是一个普通的脚本。
  • 不需要惊喜或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

显然,最好使用脚本,或者在最坏的情况下使用函数方法,直到您需要可以轻松引用的更复杂的命令。

于 2017-10-11T22:29:36.217 回答
2

如果适用,请首选该函数,因为它由执行别名的任何 shell 直接执行。使用sh -c '...'导致另一个进程启动。

于 2017-10-11T19:29:30.413 回答