在bash shell脚本中传播所有参数

时间:2011-01-28 03:34:04

标签: bash command-line-arguments

我正在编写一个调用另一个脚本的非常简单的脚本,我需要将参数从当前脚本传播到我正在执行的脚本。

例如,我的脚本名称为foo.sh,并调用bar.sh

foo.sh:

bar $1 $2 $3 $4

如何在不明确指定每个参数的情况下执行此操作?

12 个答案:

答案 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)

使用"$@"(适用于所有POSIX兼容机)。

  

[...],bash以“$ @”变量为特色,该变量扩展为以空格分隔的所有命令行参数。

来自Bash by example

答案 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的精彩摘要:

enter image description here

请注意,引号会带来所有不同,没有引号,它们的行为将完全相同。

出于我的目的,我需要按原样将参数从一个脚本传递到另一个脚本,为此,最佳选择是:

# 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'"