传播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脚本来查看真正的原始命令行,并使用引号或