$@ 与 $*
$@
的用法以及与$*
的区别可以参考 What does $@ mean in a shell script?
测试脚本如下
#!/bin/bashset -e
set -xbash -c $@
bash -c "$@"
bash -c $*
bash -c "$*"
一般情况下,我们可能会这样执行脚本
./test.sh Y=324 X=1 echo hello
输出如下,可见"$*"
会把所有的参数包裹在单引号里作为一个完整的参数,这样bash -c才能正常运行。
+ bash -c Y=324 X=1 echo hello
+ bash -c Y=324 X=1 echo hello
+ bash -c Y=324 X=1 echo hello
+ bash -c 'Y=324 X=1 echo hello'
hello
然后我们这样执行一次脚本
./test.sh "Y=324" X=1 "echo hello"
输出如下,可以看出只有"$@"
可以保证参数的一致性。如果这个脚本继续调用其他脚本,并切希望把参数继续传递下去,那么最好使用"$@"
+ bash -c Y=324 X=1 echo hello
+ bash -c Y=324 X=1 'echo hello'
+ bash -c Y=324 X=1 echo hello
+ bash -c 'Y=324 X=1 echo hello'
hello
eval
eval的作用是将其参数中的$
再执行一次。测试脚本如下,两个\\
是防止转义
#!/bin/bashecho "args:"
for ((i = 0; i <= $#; i++)); doecho " \$$i: \${$i}"
done
for ((i = 0; i <= $#; i++)); doeval "echo \" \\\$$i: \${$i}\""
done
这样执行一次脚本
./test.sh "Y=324" X=1 "echo hello"
输出如下。
args:$0: ${0}$1: ${1}$2: ${2}$3: ${3}
args:$0: ./test.sh$1: Y=324$2: X=1$3: echo hello
常见例子
整一个高难度例子看看。
init.sh的内容如下
#!/bin/bashexec 1>./logs/stdout.log
exec 2>./logs/stderr.logset -e
set -xecho "Do something here~"exec bash ./entrypoint.sh "$@"
entrypoint.sh的内容如下
#!/bin/bashexec 1>>./logs/stdout.log
exec 2>>./logs/stderr.logset -e
set -xecho "hello world!"echo "args:"
for ((i = 0; i <= $#; i++)); doeval "echo \" \\\$$i: \${$i}\""
doneexec bash -c "$*"
执行如下命令
chmod +x init.sh entrypoint.sh
./init.sh TP=4 PP=1 MBS=16 GBS=512 NLS=36 HS=4096 NAH=32 NNODES=16 SLEEP=10s bash ./entrypoint.sh echo byebye
查看stdout.log,打印出结果
Do something here~
hello world!
args:$0: ./entrypoint.sh$1: TP=4$2: PP=1$3: MBS=16$4: GBS=512$5: NLS=36$6: HS=4096$7: NAH=32$8: NNODES=16$9: SLEEP=10s$10: bash$11: ./entrypoint.sh$12: echo$13: byebye
hello world!
args:$0: ./entrypoint.sh$1: echo$2: byebye
byebye