値を失うことなく変数のエクスポートをキャンセルする方法は?

値を失うことなく変数のエクスポートをキャンセルする方法は?

変数をエクスポートするとしましょう。

foo=bar
export foo

今、エクスポートをキャンセルしたいと思います。言い換えれば、私がそうするならば、私はその環境に全くいないsh -c 'echo "$foo"'資格がありませんbar。変数の存在を示す簡単な方法の例です。コマンドは何でも構いません。コマンドの動作は、その環境に変数が存在する場合にのみ影響を受ける可能性があります。foosh -csh -c

私はできます:

  1. unset変数を作成して失います。
  2. env削除するには、各コマンドを使用します。env -u foo sh -c 'echo "$foo"'
    • 現在シェルをしばらく使用したい場合は、これは実用的ではありません。

理想的には変数の値を保存したいのですが、子プロセスに空の変数として表示されたり表示されたりしないようにしたいと思います。

私はこれを行うことができると思います:

otherfoo="$foo"; unset foo; foo="$otherfoo"; unset otherfoo

otherfooすでにあれば踏む危険があります。

これが唯一の方法ですか?標準的な方法はありますか?

答え1

標準的な方法はありません。

関数を使用すると、一時変数の使用を回避できます。次の関数は、未設定の変数を未設定のままにし、空の変数を空白のままにする役割を果たします。ただし、読み取り専用または入力された変数などのシェルの特定の機能はサポートされていません。

unexport () {
  while [ "$#" -ne 0 ]; do
    eval "set -- \"\${$1}\" \"\${$1+set}\" \"\$@\""
    if [ -n "$2" ]; then
      unset "$3"
      eval "$3=\$1"
    fi
    shift; shift; shift
  done
}
unexport foo bar

ksh、bash、およびzshでは、.unexportを使用して変数のエクスポートをキャンセルできますtypeset +x foo。これは型などの特別な属性を保持するため、使用することをお勧めします。typeset機能が組み込まれているすべてのシェルにはtypeset +x

case $(LC_ALL=C type typeset 2>&1) in
  typeset\ *\ builtin) unexport () { typeset +x -- "$@"; };;
  *) unexport () { … };; # code above
esac

答え2

編集する:bashコメントで指摘したとおりにのみ適用されます。

各名前から属性を削除する-nオプションexportexport(望むよりhelp export。)

だからのためにbash必要なコマンドは次のとおりです。export -n foo

答え3

私は同様のPOSIX関数を書いていますが、これはランダムなコードが実行される危険性はありません。

unexport()
    while case ${1##[0-9]*} in                   ### rule out leading numerics
          (*[!_[:alnum:]]*|"")                   ### filter out bad|empty names
          set "" ${1+"bad name: '$1'"}           ### prep bad name error
          return ${2+${1:?"$2"}}                 ### fail w/ above err or return 
          esac
    do    eval  set '"$'"{$1+$1}"'" "$'"$1"'" "$'@\" ###  $1 = (  $1+ ? $1 : "" )
          eval  "${1:+unset $1;$1=\$2;} shift 3"     ### $$1 = ( $1:+ ? $2 : -- )
    done

また、提供したいだけ多くのパラメータを処理します。パラメータが有効な名前ですが設定されていない場合は、自動的に無視されます。引数が無効な名前の場合はstderrに書き込み、必要に応じて停止しますが、コマンドラインで無効な名前の前にある有効な名前は処理を続けます。

私は別の方法を考えた。私はそれを好む。

unexport()
        while   unset OPTARG; OPTIND=1           ### always work w/ $1
                case  ${1##[0-9]*}    in         ### same old same old
                (*[!_[:alnum:]]*|"")             ### goodname && $# > 0 || break
                    ${1+"getopts"} : "$1"        ### $# ? getopts : ":"
                    return                       ### getopts errored or ":" didnt
                esac
        do      eval   getopts :s: '"$1" -"${'"$1+s}-\$$1\""
                eval   unset  "$1;  ${OPTARG+$1=\${OPTARG}#-}"
                shift
        done

まあ、これら両方は同じ技術をたくさん使います。デフォルトでは、シェル変数が設定されていない場合、その参照は+パラメータ拡張によって拡張されません。ただし、設定されている場合、その値に関係なく、パラメータは次のように拡張されます。${parameter+word}に拡張される予定です。word- 変数値の代わりに。したがって、シェル変数の自己検査と自己置換が成功します。

ジャネン大丈夫自己失敗。一番上の関数で間違った名前が見つかった場合は、入力してnullを$1残します$2。なぜなら、すべての引数が処理され、ループが終わったら$1私がする次のことは成功であるか、引数が無効であればシェルがreturn拡張され、スクリプトされたシェルを終了$2するからです。$1:?作成中にインタラクティブシェルに戻ります。word標準エラーとして。

2番目の宿題をしてくださいgetopts。エラー名を指定しません。代わりに、標準エラーメッセージをstderrに書き込みます。さらに重要なことは、argの値を保存することです。$OPTARG もしパラメータは最初にコレクション変数の名前です。したがって、すべての操作が完了したら、セットを適切な割り当てに拡張するgetopts必要があります。evalOPTARG

関連情報