所以情况是这样的...我有 shell 脚本文件,其中包含函数以及其他命令,例如...
#!/bin/sh
myFunc() {
for arg in "$@"; do
# ... do something with every arg passed to myFunc
done
}
# ... do something
myFunc func-arg-1
# ... do something
myFunc func-arg-2 func-arg-1
# ... do something
是否可以获取从内部传递给文件的参数myFunc
?
答案1
如果您可以使用 Bash/Ksh/Zsh,则可以将脚本的参数放入数组中并从函数内访问它们:
#!/bin/bash
args=( "$@" )
func() {
local x
for x in "$@"; do
echo "$x is an argument to the function"
done
for x in "${args[@]}"; do
echo "$x is an argument to the script"
done
}
func bla
在 POSIX shell 中,除了单个参数列表之外没有其他数组。如果您需要区分脚本参数和函数参数,您可以手动将脚本的参数传递给函数,并使用一些分隔符:
#!/bin/sh
delim=:::
func() {
delim_seen=0
for k in "$@"; do
if [ "$k" = "$delim" ]; then
delim_seen=1
continue;
elif [ "$delim_seen" = 0 ]; then
echo "$k is an argument to the function only"
else
echo "$k is an argument to the script"
fi
done
}
func bla "$delim" "$@"
当然,如果实际参数本身包含分隔符字符串,这将会失败。Stéphane 显式传递计数的解决方案当然更好,因为它不存在这个问题。
但是,无论采用哪种方法,随机访问参数几乎都是不可能的。这也适用于同时处理两个列表,即使在每个列表中按顺序处理也是如此。如果您需要这样做,我真的建议切换到一些功能更丰富的 shell,或实际的编程语言(Perl、Python 等)。
如果脚本采用的参数只是可选开关(例如-i
、 或-k foo
),则可以getopts
在调用函数之前将它们解析为单独的变量。或者,如果函数的参数更像开关,请将它们放在单独的变量中。
而且,如果函数的参数中有一些已知的结构,并且它们被认为是“好的”字符串而不是任意文件名,那么您可能能够将它们打包在单个字符串中,再次可能使用一些分隔符(字符)不能出现在值本身中。然后应用模式匹配和参数扩展来处理批次。 (或者甚至,天堂不允许,故意调用分词。)这不会很漂亮,但可能是可行的,这在很大程度上取决于细节。
答案2
在函数内部, in sh
,位置参数 ( $1
, $2
..., $@
, $*
) 是函数本身的位置参数,脚本的位置参数(如果从另一个函数中调用,则为父函数的位置参数)不再可访问。
因此,您需要以其他方式将这些参数传递给函数。
不支持数组变量并没有帮助sh
,这使得存储任意字符串列表变得困难。
除了其他人已经建议的解决方案之外,您还可以这样做:
#! /bin/sh -
myFunc() {
n="$(( $# - $1 - 1 ))" i=0; shift
for arg do
case "$i" in
("$n") break;;
(0) shift "$n";; # on first pass, remove the function arguments from "$@"
esac
i="$(( i + 1 ))"
# ... do something with every "$arg" passed to myFunc and with "$@"
done
}
并调用myFunc
为:
myFunc "$#" args for myFunc "$@"
答案3
只需将它们传递给函数即可:
myFunc func-arg-2 func-arg-1 "$@"