【问题标题】:Bash script adding arguments from variableBash脚本从变量中添加参数
【发布时间】:2018-07-18 15:07:50
【问题描述】:

我正在编写一个 Bash 脚本,如果它检测到 Java 版本大于 10,它将添加模块自定义。我似乎无法正确读取自定义作为 java 命令的参数

#!/bin/bash


# Expect format:  java full version "10.0.1+10"
jver="$( java -fullversion 2>&1)"

IFS='.-_^+^"'
read -ra ADDR <<< "$jver"    # jver is read into an array as tokens separated by IFS


#java version < 10
if [ ${ADDR[1]} -lt 10 ]; then
    moduleCustomizations=""
else
    moduleCustomizations=("--illegal-access=warn" "--add-opens java.desktop/java.awt.color=ALL-UNNAMED" "--add-opens java.desktop/sun.font=ALL-UNNAMED" "--add-opens java.desktop/java.beans=ALL-UNNAMED" "--add-opens java.base/java.lang=ALL-UNNAMED" "--add-opens java.base/java.lang.module=ALL-UNNAMED" "--add-opens java.desktop/javax.swing=ALL-UNNAMED" "--add-opens java.desktop/java.awt=ALL-UNNAMED" "--add-opens java.desktop/sun.awt.image=ALL-UNNAMED" "--add-opens java.desktop/javax.accessibility=ALL-UNNAMED" "--add-opens java.desktop/sun.awt=ALL-UNNAMED" "--add-opens java.base/jdk.internal.module=ALL-UNNAMED" "--add-opens java.base/java.security.cert=ALL-UNNAMED" "--add-opens java.base/java.security=ALL-UNNAMED" "--add-opens java.base/java.net=ALL-UNNAMED" "--add-opens java.base/java.lang.ref=ALL-UNNAMED")

fi

set -x

java "${moduleCustomizations[@]}"  -Xmx1024m com.test.myClass

通过debug,bash解释为:

java --illegal-access=warn '--add-opens java.desktop/java.awt.color=ALL-UNNAMED' '--add-opens java.desktop/sun.font=ALL-UNNAMED' '--add-opens java.desktop/java.beans=ALL-UNNAMED' '--add-opens java.base/java.lang=ALL-UNNAMED' '--add-opens java.base/java.lang.module=ALL-UNNAMED' '--add-opens java.desktop/javax.swing=ALL-UNNAMED' '--add-opens java.desktop/java.awt=ALL-UNNAMED' '--add-opens java.desktop/sun.awt.image=ALL-UNNAMED' '--add-opens java.desktop/javax.accessibility=ALL-UNNAMED' '--add-opens java.desktop/sun.awt=ALL-UNNAMED' '--add-opens java.base/jdk.internal.module=ALL-UNNAMED' '--add-opens java.base/java.security.cert=ALL-UNNAMED' '--add-opens java.base/java.security=ALL-UNNAMED' '--add-opens java.base/java.net=ALL-UNNAMED' '--add-opens java.base/java.lang.ref=ALL-UNNAMED' -Xmx1024m com.test.myClass

所以我认为问题在于单引号出现在除了传递给 java 命令的第一个项目之外的所有项目中。如何让 bash 正确传递参数?

编辑:

添加另一种方法,我尝试将 $moduleCustomizations 保留为一个字符串:

#!/bin/bash


# Expect format:  java full version "10.0.1+10"
jver="$( java -fullversion 2>&1)"

IFS='.-_^+^"'
read -ra ADDR <<< "$jver"    # jver is read into an array as tokens separated by IFS


#java version < 10
if [ ${ADDR[1]} -lt 10 ]; then
    moduleCustomizations=""
else
    moduleCustomizations="--illegal-access=warn --add-opens java.desktop/java.awt.color=ALL-UNNAMED --add-opens java.desktop/sun.font=ALL-UNNAMED --add-opens java.desktop/java.beans=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.module=ALL-UNNAMED --add-opens java.desktop/javax.swing=ALL-UNNAMED --add-opens java.desktop/java.awt=ALL-UNNAMED --add-opens java.desktop/sun.awt.image=ALL-UNNAMED --add-opens java.desktop/javax.accessibility=ALL-UNNAMED --add-opens java.desktop/sun.awt=ALL-UNNAMED --add-opens java.base/jdk.internal.module=ALL-UNNAMED --add-opens java.base/java.security.cert=ALL-UNNAMED --add-opens java.base/java.security=ALL-UNNAMED --add-opens java.base/java.net=ALL-UNNAMED --add-opens java.base/java.lang.ref=ALL-UNNAMED"

fi

set -x

java "${moduleCustomizations}"  -Xmx1024m com.test.myClass

但这变成了:

 java '--illegal-access=warn --add-opens java.desktop/java.awt.color=ALL-UNNAMED --add-opens java.desktop/sun.font=ALL-UNNAMED --add-opens java.desktop/java.beans=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.module=ALL-UNNAMED --add-opens java.desktop/javax.swing=ALL-UNNAMED --add-opens java.desktop/java.awt=ALL-UNNAMED --add-opens java.desktop/sun.awt.image=ALL-UNNAMED --add-opens java.desktop/javax.accessibility=ALL-UNNAMED --add-opens java.desktop/sun.awt=ALL-UNNAMED --add-opens java.base/jdk.internal.module=ALL-UNNAMED --add-opens java.base/java.security.cert=ALL-UNNAMED --add-opens java.base/java.security=ALL-UNNAMED --add-opens java.base/java.net=ALL-UNNAMED --add-opens java.base/java.lang.ref=ALL-UNNAMED' -Xmx1024m com.test.myClass

而 bash 将参数解释为一个大参数。

编辑2:

再试一次,但这次没有在 ${moduleCustomizations} 周围加上引号。它似乎删除了所有破折号:

java '' '' illegal 'access=warn ' '' add 'opens java' desktop/java awt color=ALL 'UNNAMED ' '' add 'opens java' desktop/sun font=ALL 'UNNAMED ' '' add 'opens java' desktop/java beans=ALL 'UNNAMED ' '' add 'opens java' base/java lang=ALL 'UNNAMED ' '' add 'opens java' base/java lang module=ALL 'UNNAMED ' '' add 'opens java' desktop/javax swing=ALL 'UNNAMED ' '' add 'opens java' desktop/java awt=ALL 'UNNAMED ' '' add 'opens java' desktop/sun awt image=ALL 'UNNAMED ' '' add 'opens java' desktop/javax accessibility=ALL 'UNNAMED ' '' add 'opens java' desktop/sun awt=ALL 'UNNAMED ' '' add 'opens java' base/jdk internal module=ALL 'UNNAMED ' '' add 'opens java' base/java security cert=ALL 'UNNAMED ' '' add 'opens java' base/java security=ALL 'UNNAMED ' '' add 'opens java' base/java net=ALL 'UNNAMED ' '' add 'opens java' base/java lang ref=ALL UNNAMED -Xmx1024m com.test.myClass

【问题讨论】:

  • 为什么不将moduleCustomizations 填充为像moduleCustomizations="--illegal-access=warn --add-opens java.desktop/java.awt.color=ALL-UNNAMED ...." 这样的单个字符串?
  • 我开始尝试这种方式,但它似乎将 moduleCustomizations 变量解释为一个大参数。我已经修改以添加一个示例
  • 请尝试使用单个字符串选项,但要像 java ${moduleCustomizations} -Xmx1024m com.test.myClass 这样调用 java。 moduleCustomizations周围没有引号
  • BashFAQ #50 直接相关。
  • Re: 不带引号的扩展删除了破折号,那是因为你在IFS 中找到了它们。 绝对不是说不带引号的扩展是您应该使用的一种做法;与任何其他单个错误相比,它可能导致更多的 BashPitfalls 条目。正如其他人的回答所示,使用数组意味着您可以在可选添加的参数中使用引用/转义/空格/等。

标签: bash shell


【解决方案1】:

问题在于您将两个独立的参数合并在一起:

"--add-opens java.desktop/java.awt.color=ALL-UNNAMED"

不要试图让它变得更难,因为你不会尝试运行:

java "--add-opens java.desktop/java.awt.color=ALL-UNNAMED"

只需将您要在 java 命令之后添加的任何内容直接放入数组中,而无需尝试添加额外的引用:

java --add-opens java.desktop/java.awt.color=ALL-UNNAMED

变成:

args=( --add-opens java.desktop/java.awt.color=ALL-UNNAMED )
java "${args[@]}"

在您的代码中:

#!/bin/bash

# Expect format:  java full version "10.0.1+10"
jver="$( java -fullversion 2>&1)"

# jver is read into an array as tokens separated by IFS
IFS='.-_^+"' read -ra ADDR <<< "$jver"    

#java version < 10
if [[ "${ADDR[1]}" -lt 10 ]]; then
    moduleCustomizations=()
else
    moduleCustomizations=(
       --illegal-access=warn
       --add-opens java.desktop/java.awt.color=ALL-UNNAMED
       --add-opens java.desktop/sun.font=ALL-UNNAMED
       --add-opens java.desktop/java.beans=ALL-UNNAMED
       --add-opens java.base/java.lang=ALL-UNNAMED
       --add-opens java.base/java.lang.module=ALL-UNNAMED
       --add-opens java.desktop/javax.swing=ALL-UNNAMED
       --add-opens java.desktop/java.awt=ALL-UNNAMED
       --add-opens java.desktop/sun.awt.image=ALL-UNNAMED
       --add-opens java.desktop/javax.accessibility=ALL-UNNAMED
       --add-opens java.desktop/sun.awt=ALL-UNNAMED
       --add-opens java.base/jdk.internal.module=ALL-UNNAMED
       --add-opens java.base/java.security.cert=ALL-UNNAMED
       --add-opens java.base/java.security=ALL-UNNAMED
       --add-opens java.base/java.net=ALL-UNNAMED
       --add-opens java.base/java.lang.ref=ALL-UNNAMED
    )
fi
set -x
java "${moduleCustomizations[@]}"  -Xmx1024m com.test.myClass

另请注意,set -x 输出中出现或未出现的任何引号都是为了您的利益而纯粹的消歧符号。他们不会更改或决定传递给命令的内容。这只是为了让您的肉眼可以分辨出参数数组之间的区别,例如(用 Java 表示法):

{"hello", "world"}
{"hello", "world", ""}
{"hello world"}
{"hello world", "", ""}

因为如果您只是附加并打印单词,所有这些不同的数组都会显示为hello world,这在调试时不是很有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-14
    • 2011-04-26
    • 2015-08-06
    • 1970-01-01
    • 1970-01-01
    • 2019-05-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多