从脚本内传递包含空格的字符串作为命令行参数

从脚本内传递包含空格的字符串作为命令行参数

我在 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-commandfoo bar争论1 和baz参数 2。(还有一个参数 0,它告诉程序它是如何运行的;shell 通过some-command它。)

使用引号使您能够告诉外壳争论开始和结束的地方。空格通常告诉 shell 将每一侧的文本视为单独的参数1,但是您想抑制空格对 shell 的特殊含义,这就是引用的作用。当引号被引用时,比如 inside ' 'inside " ",会删除他们的也有特殊意义。然后它们不会执行引用,而是按字面意思传递给您的命令,如其git日志中所示:

a382806 'one two three'

1 在shell的运行中、空格和制表符以两种相关但不同的方式将文本划分为单独的单词。第一的,当命令被首次解析时、不带引号的空格和制表符分隔词汇标记。其他元字符也可以这样做,但它们还有额外的效果——例如,;将一行分成多个命令。二、哪里参数扩展或任何其他外壳扩展由一个表示$2在未加引号的上下文中执行,结果立即受到分词, 哪个使用 中的字符$IFS作为分隔符。这默认值IFS是一个空格,后跟一个制表符,后跟一个换行符。

2或者命令替换,即使` `使用语法而不是$( )语法。

相关内容