我正在编写一个调用另一个脚本的非常简单的脚本,我需要将参数从当前脚本传播到我正在执行的脚本。
例如,我的脚本名称为foo.sh
,并调用bar.sh
foo.sh:
bar $1 $2 $3 $4
如何在不明确指定每个参数的情况下执行此操作?
答案 0 :(得分:1153)
如果您真的希望传递参数,请使用"$@"
代替普通$@
。
观察:
$ cat foo.sh
#!/bin/bash
baz.sh $@
$ cat bar.sh
#!/bin/bash
baz.sh "$@"
$ cat baz.sh
#!/bin/bash
echo Received: $1
echo Received: $2
echo Received: $3
echo Received: $4
$ ./foo.sh first second
Received: first
Received: second
Received:
Received:
$ ./foo.sh "one quoted arg"
Received: one
Received: quoted
Received: arg
Received:
$ ./bar.sh first second
Received: first
Received: second
Received:
Received:
$ ./bar.sh "one quoted arg"
Received: one quoted arg
Received:
Received:
Received:
答案 1 :(得分:459)
对于 bash 和其他类似Bourne的shell:
java com.myserver.Program "$@"
答案 2 :(得分:82)
答案 3 :(得分:30)
#!/usr/bin/env bash
while [ "$1" != "" ]; do
echo "Received: ${1}" && shift;
done;
在试图测试args如何进入你的脚本时,这可能会更有用
答案 4 :(得分:29)
我意识到这已经得到了很好的回答,但这里是" $ @"之间的比较。 $ @" $ *"和$ *
测试脚本的内容:
# cat ./test.sh
#!/usr/bin/env bash
echo "================================="
echo "Quoted DOLLAR-AT"
for ARG in "$@"; do
echo $ARG
done
echo "================================="
echo "NOT Quoted DOLLAR-AT"
for ARG in $@; do
echo $ARG
done
echo "================================="
echo "Quoted DOLLAR-STAR"
for ARG in "$*"; do
echo $ARG
done
echo "================================="
echo "NOT Quoted DOLLAR-STAR"
for ARG in $*; do
echo $ARG
done
echo "================================="
现在,使用各种参数运行测试脚本:
# ./test.sh "arg with space one" "arg2" arg3
=================================
Quoted DOLLAR-AT
arg with space one
arg2
arg3
=================================
NOT Quoted DOLLAR-AT
arg
with
space
one
arg2
arg3
=================================
Quoted DOLLAR-STAR
arg with space one arg2 arg3
=================================
NOT Quoted DOLLAR-STAR
arg
with
space
one
arg2
arg3
=================================
答案 5 :(得分:12)
这里有很多答案建议带引号和不带引号的$@
或$*
,但是似乎没有人解释它们的真正含义以及为什么要这么做。因此,让我窃取this answer的精彩摘要:
请注意,引号会带来所有不同,没有引号,它们的行为将完全相同。
出于我的目的,我需要按原样将参数从一个脚本传递到另一个脚本,为此,最佳选择是:
# file: parent.sh
# we have some params passed to parent.sh
# which we will like to pass on to child.sh as-is
./child.sh $*
请注意,没有引号,$@
在上述情况下也应适用。
答案 6 :(得分:8)
我的SUN Unix有很多限制,甚至" $ @"没有被解释为理想。我的解决方法是$ {@}。例如,
#!/bin/ksh
find ./ -type f | xargs grep "${@}"
顺便说一句,我必须拥有这个特殊的脚本,因为我的Unix也不支持grep -r
答案 7 :(得分:3)
正常工作,除非您有空格或转义字符。在这种情况下,我找不到捕获参数的方法,并发送到脚本内的ssh。
这可能很有用但很难看
_command_opts=$( echo "$@" | awk -F\- 'BEGIN { OFS=" -" } { for (i=2;i<=NF;i++) { gsub(/^[a-z] /,"&@",$i) ; gsub(/ $/,"",$i );gsub (/$/,"@",$i) }; print $0 }' | tr '@' \' )
答案 8 :(得分:2)
如果在带有其他字符的带引号的字符串中包含$@
,则当存在多个参数时,行为非常奇怪,只有第一个参数包含在引号内。
示例:
#!/bin/bash
set -x
bash -c "true foo $@"
收率:
$ bash test.sh bar baz
+ bash -c 'true foo bar' baz
但首先分配给另一个变量:
#!/bin/bash
set -x
args="$@"
bash -c "true foo $args"
收率:
$ bash test.sh bar baz
+ args='bar baz'
+ bash -c 'true foo bar baz'
答案 9 :(得分:2)
有时候您想传递所有参数,但前面要加上一个标志(例如SELECT SUBSTR(INPUT_STR,
1, INSTR(SUBSTR(INPUT_STR, (INSTR(INPUT_STR, 'abc_', -1) + 4)), '&')) AS OUTPUT_STR
FROM YOUR_TABLE
)
--flag
您可以通过以下方式进行操作:
$ bar --flag "$1" --flag "$2" --flag "$3"
注意:为避免额外的字段拆分,必须用引号$ bar $(printf -- ' --flag "%s"' "$@")
和%s
来避免单个字符串,而不能用引号{{1 }}。
答案 10 :(得分:2)
bar "$@"
将等同于bar "$1" "$2" "$3" "$4"
请注意引号很重要!
"$@"
,$@
,"$*"
或$*
各自在转义和串联方面的行为略有不同,如本stackoverflow answer中所述。
一个密切相关的用例是在参数内传递所有给定参数,如下所示:
bash -c "bar \"$1\" \"$2\" \"$3\" \"$4\""
。
我使用@kvantour答案的变体来实现这一目标:
bash -c "bar $(printf -- '"%s" ' "$@")"
答案 11 :(得分:1)
"${array[@]}"
是在bash中传递任何数组的正确方法。我想提供一个完整的备忘单:如何准备参数,绕过和处理它们。
pre.sh
-> foo.sh
-> bar.sh
。
#!/bin/bash
args=("--a=b c" "--e=f g")
args+=("--q=w e" "--a=s \"'d'\"")
./foo.sh "${args[@]}"
#!/bin/bash
./bar.sh "$@"
#!/bin/bash
echo $1
echo $2
echo $3
echo $4
结果:
--a=b c
--e=f g
--q=w e
--a=s "'d'"