我应该在 git 别名脚本中使用 `sh -c \"...\"` 还是 `"!f() {... ; }; f"?
Should I use `sh -c \"...\"` or `"!f() {... ; }; f" in git alias scripts?
我一直在尝试编写带有参数的 git 别名。我见过一些人 运行 shell 脚本
[alias]
shAlias = !sh -c \" ... \"
和其他运行函数与
[alias]
fAlias = "!f() { ... ; }; f"
似乎(一旦我加快了 Bash 的速度——这不是我现在的状态)我想做的任何事情都可以用任何一种形式完成。
在什么情况下一种优于另一种?
除了可行性之外,是否存在处理差异?内存使用/速度/等?
如果适用,请优先使用该函数,因为它直接由 shell 执行别名的任何对象执行。使用 sh -c '...'
会导致 另一个 进程启动。
TL;DR:对最简单的命令使用函数方法,一旦遇到任何类型的引用问题,就切换到外部脚本。一起避免 sh -c
。
我们可以have a look at the git source。它以 git
特定方式解析引号,如果结果没有 shell 元字符(包括 space)则作为文件执行,否则执行 execlp("sh", "-c", "result \"$@\"", "result \"$@\"", args...)
的等价物。
基于此,创建别名的最佳方法肯定是创建一个外部脚本并使用:
[alias]
myAlias = !/path/to/script
它需要一个外部文件,但在所有其他方面它更好:
- 您 运行 与您想要的任何口译员。你甚至可以 运行
bash
代码,因为你问,而其他形式只允许你 运行 sh
代码(区别就像 C++ 与 C)。
- 除非您愿意,否则不会启动其他 shell。
git
将 execve
直接执行您的可执行文件。
- 不需要转义。这只是一个普通的脚本。
- 没有惊喜,也不需要
git
知识。这只是一个脚本。
根据您的建议,运行最后一项是:
[alias]
fAlias = "!f() { ... ; }; f"
这没那么棒,因为:
- 很遗憾,您只能 运行 使用
sh
,因此不能使用任何 bash
功能。
- 一个shell总是启动,但至少它只是一个。
- 引号需要一些
git
特定的转义。
- 您需要注意
git
的转义,但通常无需确切知道它是如何执行命令的,因为您将只使用函数的参数。
最后一个是迄今为止最差的:
[alias]
shAlias = !sh -c \" ... \"
这很糟糕,因为:
- 您只能 运行 与
sh
。
- 它会无缘无故地开始额外的 shell。
- 您需要
git
转义和额外的 sh
转义级别。
- 您需要知道如何转义
sh
的代码,如何使用 git
对其进行双重转义,以及 git
如何将 "$@"
附加到您的命令如果有附加参数,则将附加参数作为 </code>、<code>
传递。
为了演示实际差异,假设您想为此命令创建别名以通过 ssh
:
获取远程服务器上的路径
ssh "" 'echo "$PATH"'
您可以将其逐字复制粘贴到文件中,添加一个 shebang,然后使用:
[alias]
get-remote-path = !/path/to/my/script
或者您可以添加一些 git
转义并使用函数方法:
[alias]
get-remote-path = "!f() { ssh \"\" 'echo \"$PATH\"'; }; f"
或者我们可以用sh -c
的方法费力地逃避再逃避(不行,没有硬道理不行):
[alias]
get-remote-path = !sh -c 'ssh \"\" '\''echo \"$PATH\"'\' cthulhu
显然,最好使用脚本,或者在最坏的情况下使用函数方法,直到您需要可以轻松引用的更复杂的命令。
我一直在尝试编写带有参数的 git 别名。我见过一些人 运行 shell 脚本
[alias]
shAlias = !sh -c \" ... \"
和其他运行函数与
[alias]
fAlias = "!f() { ... ; }; f"
似乎(一旦我加快了 Bash 的速度——这不是我现在的状态)我想做的任何事情都可以用任何一种形式完成。
在什么情况下一种优于另一种?
除了可行性之外,是否存在处理差异?内存使用/速度/等?
如果适用,请优先使用该函数,因为它直接由 shell 执行别名的任何对象执行。使用 sh -c '...'
会导致 另一个 进程启动。
TL;DR:对最简单的命令使用函数方法,一旦遇到任何类型的引用问题,就切换到外部脚本。一起避免 sh -c
。
我们可以have a look at the git source。它以 git
特定方式解析引号,如果结果没有 shell 元字符(包括 space)则作为文件执行,否则执行 execlp("sh", "-c", "result \"$@\"", "result \"$@\"", args...)
的等价物。
基于此,创建别名的最佳方法肯定是创建一个外部脚本并使用:
[alias]
myAlias = !/path/to/script
它需要一个外部文件,但在所有其他方面它更好:
- 您 运行 与您想要的任何口译员。你甚至可以 运行
bash
代码,因为你问,而其他形式只允许你 运行sh
代码(区别就像 C++ 与 C)。 - 除非您愿意,否则不会启动其他 shell。
git
将execve
直接执行您的可执行文件。 - 不需要转义。这只是一个普通的脚本。
- 没有惊喜,也不需要
git
知识。这只是一个脚本。
根据您的建议,运行最后一项是:
[alias]
fAlias = "!f() { ... ; }; f"
这没那么棒,因为:
- 很遗憾,您只能 运行 使用
sh
,因此不能使用任何bash
功能。 - 一个shell总是启动,但至少它只是一个。
- 引号需要一些
git
特定的转义。 - 您需要注意
git
的转义,但通常无需确切知道它是如何执行命令的,因为您将只使用函数的参数。
最后一个是迄今为止最差的:
[alias]
shAlias = !sh -c \" ... \"
这很糟糕,因为:
- 您只能 运行 与
sh
。 - 它会无缘无故地开始额外的 shell。
- 您需要
git
转义和额外的sh
转义级别。 - 您需要知道如何转义
sh
的代码,如何使用git
对其进行双重转义,以及git
如何将"$@"
附加到您的命令如果有附加参数,则将附加参数作为</code>、<code>
传递。
为了演示实际差异,假设您想为此命令创建别名以通过 ssh
:
ssh "" 'echo "$PATH"'
您可以将其逐字复制粘贴到文件中,添加一个 shebang,然后使用:
[alias]
get-remote-path = !/path/to/my/script
或者您可以添加一些 git
转义并使用函数方法:
[alias]
get-remote-path = "!f() { ssh \"\" 'echo \"$PATH\"'; }; f"
或者我们可以用sh -c
的方法费力地逃避再逃避(不行,没有硬道理不行):
[alias]
get-remote-path = !sh -c 'ssh \"\" '\''echo \"$PATH\"'\' cthulhu
显然,最好使用脚本,或者在最坏的情况下使用函数方法,直到您需要可以轻松引用的更复杂的命令。