我有一个 bash 函数来设置$PATH这样的——
assign-path()
{
str=$1
# if the $PATH is empty, assign it directly.
if [ -z $PATH ]; then
PATH=$str;
# if the $PATH does not contain the substring, append it with ':'.
elif [[ $PATH != *$str* ]]; then
PATH=$PATH:$str;
fi
}
Run Code Online (Sandbox Code Playgroud)
但问题是,我必须为不同的变量编写不同的函数(例如,为$CLASSPATHlikeassign-classpath()等编写另一个函数)。我找不到将参数传递给 bash 函数的方法,以便我可以通过引用访问它。
如果我有类似的东西会更好 -
assign( bigstr, substr )
{
if [ -z bigstr ]; then
bigstr=substr;
elif [[ bigstr != *str* ]]; then
bigstr=bigstr:substr;
fi
}
Run Code Online (Sandbox Code Playgroud)
任何想法,如何在 bash 中实现类似上面的东西?
Gra*_*eme 17
在bash你可以${!varname}用来扩展另一个引用的变量的内容。例如:
$ var=hello
$ foo () { echo "${!1}"; }
$ foo var
hello
Run Code Online (Sandbox Code Playgroud)
从手册页:
$ var=hello
$ foo () { echo "${!1}"; }
$ foo var
hello
Run Code Online (Sandbox Code Playgroud)
此外,要设置内容引用的变量(没有 的危险eval),您可以使用declare. 例如:
$ var=target
$ declare "$var=hello"
$ echo "$target"
hello
Run Code Online (Sandbox Code Playgroud)
因此,您可以像这样编写函数(请注意,因为如果您declare在函数中使用,则必须给出,-g否则变量将是本地的):
shopt -s extglob
assign()
{
target=$1
bigstr=${!1}
substr=$2
if [ -z "$bigstr" ]; then
declare -g -- "$target=$substr"
elif [[ $bigstr != @(|*:)$substr@(|:*) ]]; then
declare -g -- "$target=$bigstr:$substr"
fi
}
Run Code Online (Sandbox Code Playgroud)
并像这样使用它:
assign PATH /path/to/binaries
Run Code Online (Sandbox Code Playgroud)
请注意,我还更正了一个错误,其中 ifsubstr已经是 的冒号分隔成员之一的子字符串bigstr,但不是其自己的成员,则不会添加它。例如,这将允许添加/bin到PATH已经包含/usr/bin. 它使用extglob集合来匹配字符串的开头/结尾或冒号,然后是其他任何内容。没有extglob,替代方案是:
[[ $bigstr != $substr && $bigstr != *:$substr &&
$bigstr != $substr:* && $bigstr != *:$substr:* ]]
Run Code Online (Sandbox Code Playgroud)
bash 4.3 中的新功能是&-n选项:declarelocal
func() {
local -n ref="$1"
ref="hello, world"
}
var='goodbye world'
func var
echo "$var"
Run Code Online (Sandbox Code Playgroud)
打印出来hello, world。