从另一个脚本调用一个Bash脚本,用引号和空格传递它的参数

时间:2013-06-07 16:04:23

标签: bash shell double-quotes salt-stack

我在Linux上制作了两个测试bash脚本,以解决问题。

TestScript1看起来像:
    echo "TestScript1 Arguments:"
    echo "$1"
    echo "$2"
    echo "$#"
    ./testscript2 $1 $2
TestScript2看起来像:
    echo "TestScript2 Arguments received from TestScript1:"
    echo "$1"
    echo "$2"
    echo "$#"
当我以下列方式执行testscript1时:
    ./testscript1 "Firstname Lastname" testmail@domain.com  
所需的输出应为:
    TestScript1 Arguments:  
    Firstname Lastname  
    testmail@domain.com  
    2
    TestScript2 Arguments received from TestScript1:  
    Firstname Lastname  
    testmail@domain.com  
    2  
但实际输出是:
    TestScript1 Arguments:  
    Firstname Lastname  
    testmail@domain.com  
    2
    TestScript2 Arguments received from TestScript1:  
    Firstname
    Lastname      
    3  

我该如何解决这个问题?我想获得所需的输出而不是实际的输出。

4 个答案:

答案 0 :(得分:40)

在Testscript 1中引用你的args:

echo "TestScript1 Arguments:"
echo "$1"
echo "$2"
echo "$#"
./testscript2 "$1" "$2"

答案 1 :(得分:25)

您需要使用:"$@"(带引号)或"${@}"(相同,但也告诉shell变量名称的开始和结束位置)。

(不要使用:$@"$*"$*)。

例如:

#testscript1:
echo "TestScript1 Arguments:"
for an_arg in "$@" ; do
   echo "${an_arg}"
done
echo "nb of args: $#"
./testscript2 "$@"   #invokes testscript2 with the same arguments we received

我不确定我是否理解你的其他要求(你想在单引号中调用'./testscript2')所以这里有两个疯狂的猜测(改变上面的最后一行):

'./testscript2' "$@"  #only makes sense if "/path/to/testscript2" containes spaces?

./testscript2 '"some thing" "another"' "$var" "$var2"  #3 args to testscript2

请告诉我你要做的确切事情

编辑:在他的评​​论说他尝试tesscript1“$ 1”“$ 2”“$ 3”“$ 4”“$ 5”“$ 6”运行:盐'远程主机'cmd.run'./testscript2 $ 1 $ 2 $ 3 $ 4 $ 5 $ 6'

你有很多级别的中间件:主机1上的testscript1,需要运行“salt”,并给它一个字符串启动带有参数的“testscrit2”...

你可以通过以下方式“简化”:

#testscript1

#we receive args, we generate a custom script simulating 'testscript2 "$@"'
theargs="'$1'"
shift
for i in "$@" ; do
   theargs="${theargs} '$i'"
done

salt 'remote host' cmd.run "./testscript2 ${theargs}"

如果THAt不起作用,则代替运行“testscript2 $ {theargs}”,将

替换为上面的最后一行
echo "./testscript2 ${theargs}" >/tmp/runtestscript2.$$  #generate custom script locally ($$ is current pid in bash/sh/...)
scp /tmp/runtestscript2.$$ user@remotehost:/tmp/runtestscript2.$$ #copy it to remotehost
salt 'remotehost' cmd.run "./runtestscript2.$$" #the args are inside the custom script!
ssh user@remotehost "rm /tmp/runtestscript2.$$" #delete the remote one
rm /tmp/runtestscript2.$$ #and the local one

答案 2 :(得分:0)

您可以执行以下操作来解析所有参数:

注意/bin/bash的使用

testscript1:

#!/bin/bash

echo "TestScript1 Arguments:"
echo "$1"
echo "$2"
echo "$#"

# Build PARAMS to be a list of arguments
# Each wrapped in quotes and
# any existing quotes escapes with \
for var in "$@"
do
    PARAMS="$PARAMS \"${var//\"/\\\"}\""
done

# Call the second script with eval, also passing an extra parameter.
eval ./testscript2 "ExtraParam" $PARAMS

testscript2:

#!/bin/bash
echo "TestScript2 Arguments received from TestScript1:"
echo "$1"
echo "$2"
echo "$3"
echo "$#"

然后当您执行以下操作时:

./testscript1 "Firstname Lastname" testmail@domain.com  

输出将是:

TestScript1 Arguments:
Firstname Lastname
testmail@domain.com
2
TestScript2 Arguments received from TestScript1:
ExtraParam
Firstname Lastname
testmail@domain.com
3

通过使用 \"${var//\"/\\\"}\"" 以这种方式构建 PARAMS,它允许脚本正确运行,即使在参数中使用引号调用,如下所示:

./testscript1 "Firstname's Last\"name" testmail@domain.com  

输出将是:

TestScript1 Arguments:
Firstname's Last"name
testmail@domain.com
2
TestScript2 Arguments received from TestScript1:
ExtraParam
Firstname's Last"name
testmail@domain.com
3

所有引号和空格都正确地从一个脚本传递到另一个脚本。

如果您不想传递所有参数,请忽略 for 循环,只需将 eval 与相关参数一起使用。

例如:

eval ./testscript2 "\"${1//\"/\\\"}\"" "Test1" "Test2" 

${1... 表示第一个参数,使用 ${2... 表示第二个等等。

这将导致:

TestScript1 Arguments:
Firstname's Last"name
testmail@domain.com
2
TestScript2 Arguments received from TestScript1:
Firstname's Last"name
Test1
Test2
3

如果您确定永远不会在参数中使用引号,那么不要使用 "\"${1//\"/\\\"}\"",只需使用 "$1"

答案 3 :(得分:-1)

我发现以下程序适用于我

test1.sh 
a=xxx
test2.sh $a
在test2.sh中使用$1来引用test1.sh中的变量a

回音$ 1

输出为xxx