一个像其他语言一样接受参数的 bash 函数?

ram*_*rur 17 bash bash-script

我有一个 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,但不是其自己的成员,则不会添加它。例如,这将允许添加/binPATH已经包含/usr/bin. 它使用extglob集合来匹配字符串的开头/结尾或冒号,然后是其他任何内容。没有extglob,替代方案是:

[[ $bigstr != $substr && $bigstr != *:$substr &&
   $bigstr != $substr:* && $bigstr != *:$substr:* ]]
Run Code Online (Sandbox Code Playgroud)

  • @ramgorur,您可以使用`export` 将其放入您的环境中(冒着覆盖重要内容的风险)或`eval`(如果您不小心,则会出现各种问题,包括安全性)。如果使用 `eval` 你*应该*,如果你像 `eval "$target=\$substr"` 那样做。如果你忘记了 `\`,如果 `substr` 的内容中有空格,它可能会执行一个命令。 (2认同)

der*_*ert 9

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