Bash 在引用参数列表时插入额外的、不正确的单引号

问题描述 投票:0回答:3

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

它基本上是这样做的:

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

所以运行

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

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

但是 Maven 抛出了有关未知生命周期的错误。将

set -x
扔在那里告诉我该命令实际上变成了:

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

回显

$ARGUMENTS
给出预期的
"b c"
。是什么导致添加这些额外的引号以及如何修复此问题以获得预期结果?

bash
3个回答
5
投票
arguments="${*:2}"
mvn exec:java -Dexec.mainClass="$1" -Dexec.args="$arguments"

请参阅 BashFAQ #50 了解完整说明。也就是说:

"$@"
保持 argv 数组元素之间的分割——也就是说,当
--foo="$@"
时,
set -- hello world
解析为
"--foo=hello" "world"

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

$*
,没有双引号,执行相同的操作,但无法防止字符串分割或全局扩展,从而组合所有参数,但随后允许 shell 再次将它们分开(并扩展它们包含的全局)——一种行为这是非常罕见的。

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

  • 发生句法分析。正是在这个阶段,并且只有在这个阶段,shell 才决定引用哪些字符以及如何引用。因为 -Dexec.args=$arguments 中不存在文字引号,所以唯一的扩展被记录为不带引号。
    发生膨胀。此时,展开的字符串看起来像 
  • -Dexec.args="hello world"
  • 发生字符串分割。因为解析阶段已经处理、记录并删除了句法引号,所以剩下的任何引号都是数据,并被处理成单独的单词。因此,
  • -Dexec.args="hello
  • 是一个单词,
    world"
    是一个单词。
    
    
    
  • 将此与正确用法
-Dexec.args="$arguments"

(或其有效等效项

"-Dexec.args=$arguments"
)进行比较。此时:

发生句法分析。这会删除
    $arguments
  • 周围的双引号,并将其中的扩展标记为双引号。
    发生膨胀。如果 
  • arguments
  • 数组中仍有文字引号,它们将被替换为数据,使
    -Dexec.args="hello world"
    成为传递给 Maven 的文字数据,
    包括
    引号字符本身。 字符串分割发生在扩展字符串上。在这种情况下,因为语法解析将扩展标记为双引号,所以它没有任何效果。
  • 如果您不希望将文字引号字符传递给 Maven(您不应该!),只需省略它们,并仅使用语法引号,如本答案顶部的示例所示。


3
投票

arr=( "$@" ) mvn exec:java -Dexec.mainClass="$1" -Dexec.args="${arr[*]:1}"



0
投票

格伦·杰克曼的“对文字引号进行硬编码通常是一个错误”

什么不起作用

T CUCUMBER_TAGS="\"@happy_path and @disabled\"" mvn verify '-Dcucumber.filter.tags="@happy_path and @disabled"'

Bash 添加单引号,但在单引号 mvn 属性内时,
cucumber.filter.tags

并不真正使用双引号中的标签。我认为它会工作,因为这可以在命令行中以非 bash 脚本方式工作

mvn verify -Dcucumber.filter.tags="@happy_path and @disabled"

什么解决了它

变量中没有双引号

enter code here CUCUMBER_TAGS="@happy_path and @disabled" mvn verify '-Dcucumber.filter.tags=@happy_path and @disabled'

另外,对于这里的原始问题

我认为这会起作用 ARGUMENTS="${@:2}" mvn exec:java -Dexec.mainClass=$1 -Dexec.args=$ARGUMENTS

这会导致(有效吗?)

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

© www.soinside.com 2019 - 2024. All rights reserved.