以下方法几乎有效:
#!/bin/bash
/* 2>&1 >/dev/null
script_dir=$(dirname "$0")
export GROOVY_HOME=${script_dir}/../../../../Tools/groovy/groovy-2.0.2
exec ${GROOVY_HOME}/bin/groovy -cp "${script_dir}:$(ls ${script_dir}/build/lib/runtime/*.jar | xargs echo | sed -e 's| |:|g')" "$0"
*/ // 2>&1 >/dev/null
println("aoeu")
唯一的问题是 shell 会 glob/* 并尝试执行它。最后,我真正想做的是能够构建Groovy脚本的类路径,而不必有两个单独的脚本。
您也可以尝试以下技术,该技术独立于Groovy语法(并且通常不会在stderr
上产生输出):
#!/bin/sh
script_dir=$(dirname "$0")
export GROOVY_HOME="$script_dir/../../../../Tools/groovy/groovy-2.0.2"
awk 'mark_on{print}/^__END__$/{mark_on=1}' "$0" >/tmp/$$.groovy
"$GROOVY_HOME/bin/groovy" -cp "$script_dir:$(echo "$script_dir"/build/lib/runtime/*.jar | tr " " :)" /tmp/$$.groovy
status=$?
rm -f /tmp/$$.groovy
exit $status
__END__
println("aoeu")
还要注意类路径计算中的简化;请记住,通配符扩展是由 shell 执行的,而不是由接受参数的命令执行的,因此在这种情况下您不必(也不想)使用ls
。
在这种情况下,原始代码中${}
的大括号在技术上是多余的(它们纯粹是样式性的);例如,如果您必须直接在变量替换之后附加一个字符串,其中变量名称和后面的内容之间没有明显的分隔符,则需要它们,例如,您不能说$my_varsome_string
但您可以写${my_var}some_string
, 或任何$my_var"some_string"
或$my_var'some_string'
或"$my_var"some_string
或"$my_var""some_string"
。 我出于"简约"目的删除了大括号,为了说明上述内容,但同样,出于风格原因保留它们是完全可以的。
我在上面的代码中一致添加的引号可以保护您免受$GROOVY_HOME
中潜在的空白和某些其他特殊字符的影响。如果您知道$GROOVY_HOME
不包含空格,请随意删除它们以简化引用(并保持简约)。
看来你想写一个时髦/壳的多语言。
我不知道 groovy,但从文档中看,[] 似乎是一个有效的 groovy 命令,创建了一个空列表。
然后你可以这样写:
#!/bin/bash
[ /* 2> /dev/null > /dev/null
script_dir=$(dirname "$0")
export GROOVY_HOME=${script_dir}/../../../../Tools/groovy/groovy-2.0.2
exec ${GROOVY_HOME}/bin/groovy -cp "${script_dir}:$(ls ${script_dir}/build/lib/runtime/*.jar | xargs echo | sed -e 's| |:|g')" "$0"
*/
]
println("aoeu")
Groovy将读取[]并忽略它,bash将使用/*调用[,这将导致忽略的错误。但它不会运行任何意外的程序。
#!/bin/bash
script_dir="$(cd $(dirname $0) >/dev/null; pwd -P)"
function after-bangshe() {
sed -e '1,/^!#$/d' "$1"
}
if [ -z "${GROOVY_HOME}" ]
then
echo 'GROOVY_HOME must be defined.' >&2
exit 1
fi
CLASSPATH="${script_dir}" "${GROOVY_HOME}/bin/groovy" -e "$(after-bangshe $0)" "$@"
exit
!#
println 'aoeu'
cd
的输出在设置CDPATH
的情况下重定向到/dev/null
(这会cd
嘈杂)。
CLASSPATH
设置为脚本目录,以便可以找到任何支持类。
sed
命令会去除!#
行之后的所有内容。