bash関数は他の言語と同じようにパラメータを受け入れますか?

bash関数は他の言語と同じようにパラメータを受け入れますか?

$PATH次のように設定できるbash機能があります。

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
}

しかし、問題は、異なる変数に対して別の関数を作成する必要があることです(たとえば、類似の関数に対して$CLASSPATH別の関数を作成するassign-classpath()など)。参照としてアクセスできるように bash 関数にパラメータを渡す方法が見つかりません。

似たようなものがあればもっといいと思います -

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

bashで上記のようなものを実装する方法を知っていますか?

答え1

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

substrifがすでにコロンで区切られたメンバーの1つのサブストリングですが、それbigstr自体のメンバーではない場合に追加されないバグも修正されました。たとえば、すでに含まれているもの/binに追加できます。これは、文字列やコロンの開始/終了などの項目を一致させるためにセットを使用します。そうでない場合、代替は次のとおりです。PATH/usr/binextglobextglob

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

答え2

Bash 4.3の新機能は&-nオプションです。declarelocal

func() {
    local -n ref="$1"
    ref="hello, world"
}

var='goodbye world'
func var
echo "$var"

出力されるのはですhello, world

答え3

パラメータの設定に使用できますeval。このコマンドのガイドラインは以下にあります。ここ。次の使用法はeval正しくありません。

無効(){
  評価$1=$2
}

追加の評価にはeval以下を使用する必要があります。

分配する(){
  評価$1='$2'
}

次の機能を使用した結果を確認してください。

$X1='$X2'
$X2='$X3'
$X3='xxx'
$
$エコ:$X1:
:$X2:
$エコ:$X2:
:$X3:
$エコ:$X3:
:トリプルX:
$
$エラーY $X1
$エコ:$Y:
:$X3:
$
$割り当てY $X1
$エコ:$Y:
:$X2:
$
$Y "hello world" 割り当て
$エコ:$Y:
:こんにちは世界:
$#次の内容は予期しない内容かもしれません。
$割り当てZ $ Y
$echo ":$Z:"
:こんにちは:
$ # したがって、2 番目のパラメータが変数の場合は、引用符で囲む必要があります。
$割り当てZ "$Y"
$echo ":$Z:"
:こんにちは世界:

ただし、それを使用せずに目標を達成できますeval。私はこの簡単な方法を好む。

次の関数は正しい方法で置換を実行します。 (希望)

増加する(){
  地域電流=$1
  ローカル増分=$2
  地域の新しい
  if [[ -z $CURRENT ]];
    新しい=$改善
  エリーフ[[! ( ( $CURRENT = $AUGMENT ) || ( $CURRENT = $AUGMENT:* ) || \
    ( $current = *:$AUGMENT ) || ( $current = *:$AUGMENT:* ) ] ]];
    新規=$現在:$改善
  その他
    新しい=$現在
    フィリピン諸島
  エコ「$鳥」
}

次の出力を確認してください。

拡張 /usr/bin /bin
/usr/bin:/bin

拡張 /usr/bin:/bin /bin
/usr/bin:/bin

拡張 /usr/bin:/bin:/usr/local/bin /bin
/usr/bin:/bin:/usr/local/bin

/bin:/usr/bin /bin 強化
/bin:/usr/bin

/bin /bin 強化
/ゴミ箱


/usr/bin 拡張: /bin
/usr/bin::/bin

拡張 /usr/bin:/bin: /bin
/usr/bin:/bin:

/usr/bin:/bin:/usr/local/bin:/bin を展開します。
/usr/bin:/bin:/usr/local/bin:

/bin:/usr/bin: /bin 強化
/bin:/usr/bin:

/binの強化: /bin
/ゴミ箱:


改善:/bin
::/ゴミ箱


"/usr lib" "/usr bin" を展開します。
/usrlib:/usrbin

"/usr lib:/usr bin" "/usr bin" を展開します。
/usrlib:/usrbin

この関数を使用して、augment次の方法で変数を設定できます。

PATH=`PATH /bin 拡張`
CLASSPATH=`CLASSPATH /bin 追加`
LD_LIBRARY_PATH=`拡張LD_LIBRARY_PATH /usr/lib`

答え4

assign () 
{ 
    if [ -z ${!1} ]; then
        eval $1=$2
    else
        if [[ ${!1} != *$2* ]]; then
            eval $1=${!1}:$2
        fi
    fi
}

$ echo =$x=
==
$ assign x y
$ echo =$x=
=y=
$ assign x y
$ echo =$x=
=y=
$ assign x z
$ echo =$x=
=y:z=

これは適切ですか?

関連情報