Bash在引用参数列表时插入多余的,不正确的单引号 [英] Bash inserting extra, incorrect single quotes when quoting argument list

查看:65
本文介绍了Bash在引用参数列表时插入多余的,不正确的单引号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试制作一个将使用某些参数运行Maven的程序.

I'm trying to make a program that will run Maven with certain arguments.

基本上是这样做的:

ARGUMENTS=\""${@:2}"\"
mvn exec:java -Dexec.mainClass=$1 -Dexec.args=$ARGUMENTS

因此,运行 ./myScript.sh a b c 应该会导致运行:

So running ./myScript.sh a b c should result in running:

mvn exec:java -Dexec.mainClass=a -Dexec.args="b c"

但是Maven抛出有关未知生命周期的错误.在其中扔 set -x 告诉我该命令实际上变成了:

But Maven is throwing errors about an unknown life cycle. Throwing set -x in there tells me that the command is actually turning into:

mvn exec:java -Dexec.mainClass=a '-Dexec.args="b' 'c"'

回显 $ ARGUMENTS 会得到预期的"b c" .是什么导致这些多余的引号被添加,如何解决这个问题以获得预期的结果?

Echoing $ARGUMENTS gives the expected "b c". What's causing these extra quotes to be added and how can I fix this to get my intended results?

推荐答案

arguments="${*:2}"
mvn exec:java -Dexec.mainClass="$1" -Dexec.args="$arguments"

有关完整说明,请参见 BashFAQ#50 .那说:

See BashFAQ #50 for a full explanation. That said:

"$ @" 维护argv数组元素之间的分隔-也就是说,当设置时,-foo ="$ @" --hello world ,解析为-foo = hello""world" .

"$@" maintains the split between argv array elements -- which is to say that --foo="$@", when set -- hello world, resolves to "--foo=hello" "world".

"$ *" 将argv数组元素与它们之间的 IFS 的第一个字符组合在一起,默认情况下为空格.

"$*" combines argv array elements with the first character of IFS between them, which is by default a space.

$ * ,不带双引号的功能相同,但是无法防止字符串拆分或glob扩展,因此将所有参数组合在一起,但随后允许Shell再次将它们分开(并扩展它们包含的小球)-一种极少希望的行为.

$*, without the double quotes, does the same but fails to prevent string-splitting or glob expansion, thus combining all arguments, but then allowing the shell to split them apart again (and expand globs they contain) -- a behavior which is very rarely desirable.

arguments ="\" $ {*:2} \" 创建一个字符串-"hello world" .当您运行 -Dexec.args = $ arguments 时,将经历多个处理阶段(不包括与当前数据集无关的阶段,例如全局扩展):

arguments="\"${*:2}\"" creates a string -- "hello world". When you run -Dexec.args=$arguments, this goes through several phases of processing (excluding ones irrelevant to your current dataset, such as glob expansion):

  • 进行语法分析.当外壳程序确定哪些字符被引用以及如何引用时,这是在此阶段,并且仅在此阶段.因为 -Dexec.args = $ arguments 中没有文字引号,所以唯一的扩展记录为未引号.
  • 发生扩展.此时,扩展的字符串看起来像 -Dexec.args ="hello world"
  • 发生字符串拆分.由于解析阶段已经处理,记录和删除了句法引号,因此剩余的所有引号都是数据,并被处理成单个单词.因此, -Dexec.args ="hello 是一个单词,而 world" 是一个单词.
  • Syntactic parsing occurs. It is at this stage, and only at this stage when the shell determines which characters are quoted and how. Because no literal quotes exist in -Dexec.args=$arguments, the only expansion is recorded as unquoted.
  • Expansion occurs. At this point, the expanded string look like -Dexec.args="hello world"
  • String-splitting occurs. Because the parsing stage already processed, recorded and removed syntactic quotes, any quotes remaining are data, and are processed into individual words. Thus, -Dexec.args="hello is a word, and world" is a word.

将其与正确的用法 -Dexec.args ="$ arguments" (或其有效等效项,-Dexec.args = $ arguments" )进行比较.此时:

Compare this to the correct usage, -Dexec.args="$arguments" (or its effective equivalent, "-Dexec.args=$arguments"). At this point:

  • 进行语法分析.这样会删除 $ arguments 周围的双引号,并将其中的扩展标记为双引号.
  • 发生扩展.如果您仍然在 arguments 数组中使用文字引号,则会将它们替换为数据,从而使 -Dexec.args ="hello world" 成为传递给Maven的文字数据,包括引号字符本身.
  • 字符串拆分发生在扩展的字符串上.在这种情况下,由于语法分析将扩展标记为双引号,因此无效.
  • Syntactic parsing occurs. This removes the double quotes around $arguments, and flags the expansion within as double-quoted.
  • Expansion occurs. If you still have literal quotes inside the arguments array, they're substituted in as data, making -Dexec.args="hello world" the literal data passed to Maven, including the quote characters themselves.
  • String splitting occurs on expanded strings. In this case, because syntactic parsing flagged the expansion as double-quoted, it has no effect.

如果您不希望将文字引号引起来的字符传递给Maven(并且您不应该!),只需忽略它们,而仅使用语法引号即可,如此答案顶部的示例中所示.

If you don't want literal quote characters passed to Maven (and you shouldn't!), simply omit them, and use only syntactic quotes, as done in the example at the top of this answer.

这篇关于Bash在引用参数列表时插入多余的,不正确的单引号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆