我正在尝试制作一个程序,该程序将使用某些参数运行 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"
。是什么导致添加这些额外的引号以及如何修复此问题以获得预期结果?
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
时,会经历几个处理阶段(排除与当前数据集无关的阶段,例如全局扩展):
-Dexec.args=$arguments
中不存在文字引号,所以唯一的扩展被记录为不带引号。发生膨胀。此时,展开的字符串看起来像 -Dexec.args="hello world"
-Dexec.args="hello
world"
是一个单词。
-Dexec.args="$arguments"
(或其有效等效项
"-Dexec.args=$arguments"
)进行比较。此时:发生句法分析。这会删除
$arguments
arguments
-Dexec.args="hello world"
成为传递给 Maven 的文字数据,包括引号字符本身。 字符串分割发生在扩展字符串上。在这种情况下,因为语法解析将扩展标记为双引号,所以它没有任何效果。
arr=( "$@" )
mvn exec:java -Dexec.mainClass="$1" -Dexec.args="${arr[*]:1}"
格伦·杰克曼的“对文字引号进行硬编码通常是一个错误”
什么不起作用
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'