我在 mac 上使用 bash shell。
我想编写一个 shell 脚本“gac”,以便运行
> gac one two three
产生确切地和跑步的效果一样
> git add .
> git commit -m "one two three"
到目前为止我的脚本是这样的:
function gac() {
git add .
concatenated="'$*'"
git commit -m "$concatenated"
}
我找到了将 shell 参数连接成单个空格分隔字符串的技巧(脚本的第二行)这里。上面的脚本几乎可以工作,除了日志消息读取
a382806 'one two three'
当我使用 shell 脚本时,而不是
a382806 one two three
当我手动输入时
> git commit -m "one two three"
在命令行上。
有任何想法吗?
答案1
当你放置双引号周围扩张, 如那个参数扩展 $*
,扩展后的文本不受分词。 (这是在扩展周围使用双引号的原因之一$
;另一个是为了防止通配.)此外,在双引号内,单引号没有被特殊对待,所以他们不执行引用,并且他们不已删除。
这样迈克尔·霍默 说,你可以只省略虚假 '
'
标记你的功能应该可以工作。我建议这样写:
gac() {
git add .
git commit -m "$*"
}
您可以使用function
关键字在 Bash 中定义函数,但上面显示的语法同样有效,并且可以跨 Bourne 风格的 shell 移植。
为了更直接地解决这里的概念问题,原始代码中的这一行表明您想要扩展一个值包含空格的参数,这样您就可以将其作为单个参数传递给git
:
concatenated="'$*'"
当您自己编写包含空格的单个参数时,您需要引用空格,通常在整个字符串周围加上引号。的存在'
'
里面该"
"
行中的 告诉我您正在尝试包含您通常会输入的引号。
该方法不起作用的原因是shell 本身会解释你的引用;它们通常对您从 shell 运行的命令没有任何意义。假设您有以下命令:
some-command 'foo bar' baz
该命令实际上并未将任何引号传递给该some-command
命令。相反,它运行some-command
为foo bar
争论1 和baz
参数 2。(还有一个参数 0,它告诉程序它是如何运行的;shell 通过some-command
它。)
使用引号使您能够告诉外壳争论开始和结束的地方。空格通常告诉 shell 将每一侧的文本视为单独的参数1,但是您想抑制空格对 shell 的特殊含义,这就是引用的作用。当引号被引用时,比如 inside '
'
inside "
"
,会删除他们的也有特殊意义。然后它们不会执行引用,而是按字面意思传递给您的命令,如其git
日志中所示:
a382806 'one two three'
1 在shell的运行中、空格和制表符以两种相关但不同的方式将文本划分为单独的单词。第一的,当命令被首次解析时、不带引号的空格和制表符分隔词汇标记。其他元字符也可以这样做,但它们还有额外的效果——例如,;
将一行分成多个命令。二、哪里参数扩展或任何其他外壳扩展由一个表示$
2在未加引号的上下文中执行,结果立即受到分词, 哪个使用 中的字符$IFS
作为分隔符。这默认值IFS
是一个空格,后跟一个制表符,后跟一个换行符。
2或者命令替换,即使`
`
使用语法而不是$(
)
语法。