传播bashshell脚本中的所有参数

传播bashshell脚本中的所有参数,bash,command-line-arguments,Bash,Command Line Arguments,我正在编写一个调用另一个脚本的非常简单的脚本,我需要将参数从当前脚本传播到我正在执行的脚本 例如,我的脚本名是foo.sh并调用bar.sh foo.sh: bar $1 $2 $3 $4 如何在不明确指定每个参数的情况下执行此操作?对于bash和其他类似Bourne的shell: java com.myserver.Program "$@" 使用“$@”(适用于所有兼容程序) […],bash的特点是“$@”变量,它扩展到所有由空格分隔的命令行参数 从。如果确实希望传递相同的参数,请使用“

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

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

foo.sh:

bar $1 $2 $3 $4
如何在不明确指定每个参数的情况下执行此操作?

对于bash和其他类似Bourne的shell:

java com.myserver.Program "$@"
使用
“$@”
(适用于所有兼容程序)

[…],bash的特点是“$@”变量,它扩展到所有由空格分隔的命令行参数

从。

如果确实希望传递相同的参数,请使用
“$@”
而不是普通的
$@

注意:

$ cat no_quotes.sh
#!/bin/bash
echo_args.sh $@

$ cat quotes.sh
#!/bin/bash
echo_args.sh "$@"

$ cat echo_args.sh
#!/bin/bash
echo Received: $1
echo Received: $2
echo Received: $3
echo Received: $4

$ ./no_quotes.sh first second
Received: first
Received: second
Received:
Received:

$ ./no_quotes.sh "one quoted arg"
Received: one
Received: quoted
Received: arg
Received:

$ ./quotes.sh first second
Received: first
Received: second
Received:
Received:

$ ./quotes.sh "one quoted arg"
Received: one quoted arg
Received:
Received:
Received:

我只是想,当尝试测试arg如何进入脚本时,这可能会更有用一些

我的SUN Unix有很多限制,即使“$@”没有按需要解释。我的解决方法是${@}。比如说,

#!/bin/ksh
find ./ -type f | xargs grep "${@}"

顺便说一句,我必须有这个特定的脚本,因为我的Unix也不支持grep-r,除非有空格或转义字符。在本例中,我找不到捕获参数并发送到脚本内部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 '@' \' )

\u command\u opts=$(echo“$@”| awk-F \-”BEGIN{OFS=“-”}{for(i=2;i我意识到这已经得到了很好的回答,但这里是“$@”$@“$*”和$*

测试脚本的内容:

# 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
=================================

如果将
$@
与其他字符一起包含在带引号的字符串中,则当存在多个参数时,行为非常奇怪,只有第一个参数包含在引号中

例如:

#!/bin/bash
set -x
bash -c "true foo $@"
收益率:

$ bash test.sh bar baz
+ bash -c 'true foo bar' baz
$ bash test.sh bar baz
+ args='bar baz'
+ bash -c 'true foo bar baz'
但首先要分配给不同的变量:

#!/bin/bash
set -x
args="$@"
bash -c "true foo $args"
收益率:

$ bash test.sh bar baz
+ bash -c 'true foo bar' baz
$ bash test.sh bar baz
+ args='bar baz'
+ bash -c 'true foo bar baz'

有时,您希望传递所有参数,但前面有一个标志(例如,
--flag

您可以通过以下方式执行此操作:

$ bar $(printf -- ' --flag "%s"' "$@")
注意:为了避免额外的字段拆分,您必须引用
%s
$@
,并且为了避免使用单个字符串,您不能引用
printf
的子shell。

条“$@”
将等同于
条“$1”“$2”“$3”“$4”

请注意,引号很重要

“$@”
$@
“$*”
$*
在转义和连接方面的行为将略有不同,如本节所述

一个密切相关的用例是在一个参数中传递所有给定参数,如下所示:

bash-c“bar\”$1\“$2\”$3\“$4\”

我使用@kvantour答案的变体来实现这一点:


bash-c“bar$(printf--''%s''“$”)”

这里有很多答案推荐
$@
$*
加引号和不加引号,但似乎没有人能解释它们到底起什么作用以及为什么要这样做。因此,让我从以下网站中窃取这篇精彩的总结:

+--------+---------------------------+
|语法|有效结果|
+--------+---------------------------+
|$*|$1$2$3…${N}|
+--------+---------------------------+
|$@|$1$2$3…${N}|
+--------+---------------------------+
|“$*”|“$1c$2c$3c…c${N}”|
+--------+---------------------------+
|“$@”|“$1”$2“$3”…“${N}”|
+--------+---------------------------+
请注意,引号会产生所有差异,没有引号,两者的行为都相同

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

#文件:parent.sh
#我们已将一些参数传递给parent.sh
#我们希望按原样传递给child.sh
//child.sh$*
请注意,没有引号,
$@
在上述情况下也应该有效。

“${array[@]}”
是在bash中传递任何数组的正确方法。我想提供一个完整的备忘单:如何准备参数、绕过和处理它们

pre.sh
->
foo.sh
->
bar.sh

!/bin/bash
args=(“--a=bc”“--e=fg”)
args+=(“--q=we”“--a=s\'d'\”“)
./foo.sh“${args[@]}”
!/bin/bash
./bar.sh“$@”
!/bin/bash
回声1美元
回声2美元
回声3美元
回声4美元
结果:

--a=b c
--e=f g
--q=w e
--a=s "'d'"

@阿米尔:不,不适用于csh。为了每个人的理智:。但我认为,
$argv:q
可能适用于某些csh变体。谢谢!根据需要,这将传递脚本收到的同一组参数,而不是一个大参数。双引号是必需的。即使使用带引号的参数(包括空格)也可以工作。相关:如果您的shell脚本是只需充当包装器来运行java,考虑最后一行<代码> Excjava java .MyServ.Actudio程序“$@”/CODE >,这会导致BASH到Java中运行,而不是等待它完成。因此,如果使用父进程(运行脚本),则使用较少的进程槽。正在通过pid监视它,并期望它是“java”进程,如果您不执行exec,一些不寻常的事情可能会中断;exec会导致java继承相同的pid。@dragonxlwang:如果您的shell支持数组变量,您可以使用数组变量(例如bash、zsh等,但不是普通的Bourne或POSIX shell):使用
args=(“$@”)保存到args
并将每个元素扩展为一个单独的shell“word”(类似于
“$@”
)和
“${args[@]}”
。使用
“$@”时是否需要记住任何“gotchas”
,例如,如果参数中有转义空格、空字符或其他特殊字符,它会失败吗?这对引用/转义字符串的纯传递有效:注意:cat rsync_foo.sh!/bin/bash echo“$@”rsync“$@”。/rsync_foo.sh-n“bar me”bar2 bar me bar2 Skiping directory bar me是否可以使用shell脚本来查看真正的原始命令行,并使用引号或