Bash

一個像其他語言一樣接受參數的bash函式?

  • July 12, 2019

我有一個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
}

但問題是,我必須為不同的變數編寫不同的函式(例如,為$CLASSPATHlikeassign-classpath()等編寫另一個函式)。我找不到將參數傳遞給 bash 函式的方法,以便我可以通過引用訪問它。

如果我有類似的東西會更好——

assign( bigstr, substr )
{
   if [ -z bigstr ]; then
       bigstr=substr;
   elif [[ bigstr != *str* ]]; then
       bigstr=bigstr:substr;
   fi
}

任何想法,如何在 bash 中實現類似上面的東西?

bash你可以使用${!varname}擴展另一個內容所引用的變數。例如:

$ var=hello
$ foo () { echo "${!1}"; }
$ foo var
hello

從手冊頁:

${!prefix*}
${!prefix@}
      Names matching prefix.  Expands to the names of variables whose names
      begin with prefix, separated by the first character of the IFS special
      variable.  When @ is used  and the expansion appears within double quotes,
      each variable name expands to a separate word.

此外,要設置內容引用的變數(沒有 的危險eval),您可以使用declare. 例如:

$ var=target
$ declare "$var=hello"
$ echo "$target"
hello

因此,您可以像這樣編寫函式(請注意,因為如果您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
}

並像這樣使用它:

assign PATH /path/to/binaries

請注意,我還糾正了一個錯誤,如果 ifsubstr已經是 的冒號分隔成員之一的子字元串bigstr,但不是它自己的成員,則不會添加它。例如,這將允許添加/binPATH已經包含/usr/bin. 它使用extglob集合來匹配字元串的開頭/結尾或冒號,然後再匹配其他任何內容。如果沒有extglob,替代方案將是:

[[ $bigstr != $substr && $bigstr != *:$substr &&
  $bigstr != $substr:* && $bigstr != *:$substr:* ]]

引用自:https://unix.stackexchange.com/questions/122632