set -x
ランダムに設定するよりも、スクリプトの先頭で「元に戻す」(設定前の状態に戻る)したいと思います+x
。これは可能ですか?
PS:確認しましたここ;私が知っている限り、これは私の質問に対する答えではないようです。
答え1
抽象的な
を元に戻すset -x
場合set +x
。ほとんどの場合、文字列の反対は:と同じ文字列set -str
です。+
set +str
通常、すべてのerrexit
シェルオプション(bashについては以下を参照)を復元するには(コマンドを使用して変更されますset
)、次のことができます(bashshopt
オプションについても以下を参照)。
oldstate="$(set +o)" # POSIXly store all set options.
.
.
set -vx; eval "$oldstate" # restore all options stored.
十分ですが、bashにはset
(or)と一部を介してshopt -po
アクセスされる2つのオプションセットがあります。また、bashはshopt -p
サブシェルに入ってもset -e
持続しません。拡張によって生成されたオプションのリストは、$-
シェルに再入力されない可能性があります。
bash で現在の状態全体をキャプチャするには、次のようにします。
oldstate="$(shopt -po; shopt -p)"; [[ -o errexit ]] && oldstate="$oldstate; set -e"
inherit_errexit
または、フラグ設定が気に入らない場合(そしてbashは≥4.4です):
shopt -s inherit_errexit; oldstate="$(shopt -po; shopt -p)"
より長い説明
強く打つ
このコマンドは次のとおりです。
shopt -po xtrace
オプションの状態を反映する実行可能な文字列を生成するために使用されます。フラグはp
印刷を意味し、フラグはコマンドによって設定されたオプション(オプションセットではない)o
について尋ねることを指定します。set
ただコマンドを介してshopt
)。この文字列を変数に割り当て、スクリプトの最後で実行して初期状態を復元できます。
# store state of xtrace option.
tracestate="$(shopt -po xtrace)"
# change xtrace as needed
echo "some commands with xtrace as externally selected"
set -x
echo "some commands with xtrace set"
# restore the value of xtrace to its original value.
eval "$tracestate"
このソリューションは複数のオプションと同時に動作します。
oldstate="$(shopt -po xtrace noglob errexit)"
# change options as needed
set -x
set +x
set -f
set -e
set -x
# restore to recorded state:
set +vx; eval "$oldstate"
set +vx
長いオプションのリストを印刷しないように追加されました。
オプション名をリストしない場合
oldstate="$(shopt -po)"
すべての(設定)オプションの値を提供します。フラグを省略すると、オプションを使用して同じ操作を実行o
できます。shopt
# store state of dotglob option.
dglobstate="$(shopt -p dotglob)"
# store state of all options.
oldstate="$(shopt -p)"
オプションが設定されていることをテストする必要がある場合、set
最も慣用的な方法は次のとおりです。
[[ -o xtrace ]]
これは他の2つの同様のテストよりも優れています。
[[ $- =~ x ]]
[[ $- == *x* ]]
すべてのテストで次のように動作します。
# record the state of the xtrace option in ts (tracestate):
[ -o xtrace ] && ts='set -x' || ts='set +x'
# change xtrace as needed
echo "some commands with xtrace as externally selected"
set -x
echo "some commands with xtrace set"
# set the xtrace option back to what it was.
eval "$ts"
オプションの状態をテストする方法は次のとおりですshopt
。
if shopt -q dotglob
then
# dotglob is set, so “echo .* *” would list the dot files twice.
echo *
else
# dotglob is not set. Warning: the below will list “.” and “..”.
echo .* *
fi
POSIX
すべてのオプションを保存するための簡単なPOSIX互換ソリューションはset
次のとおりです。
set +o
これはPOSIX規格に記載されているように:
+o
同じオプション設定を実装するコマンドでシェルに再入力するのに適した形式で、現在のオプション設定を標準出力に書き込みます。
簡単に言えば、
oldstate=$(set +o)
set
このコマンドで設定されたすべてのオプションの値は(一部のシェルでは)保持されます。
同様に、オプションを元の値に復元することは、単に変数を実行する問題です。
set +vx; eval "$oldstate"
これはBashを使用するのと同じですshopt -po
。いいえ書くみんな可能吹くオプションの一部のみが提供されるためですshopt
。
バッシュ特別な場合
shopt
Bashには他の多くのシェルオプションがリストされています。
$ shopt
autocd off
cdable_vars off
cdspell off
checkhash off
checkjobs off
checkwinsize on
cmdhist on
compat31 off
compat32 off
compat40 off
compat41 off
compat42 off
compat43 off
complete_fullquote on
direxpand off
dirspell off
dotglob off
execfail off
expand_aliases on
extdebug off
extglob off
extquote on
failglob off
force_fignore on
globasciiranges off
globstar on
gnu_errfmt off
histappend on
histreedit off
histverify on
hostcomplete on
huponexit off
inherit_errexit off
interactive_comments on
lastpipe on
lithist off
login_shell off
mailwarn off
no_empty_cmd_completion off
nocaseglob off
nocasematch off
nullglob off
progcomp on
promptvars on
restricted_shell off
shift_verbose off
sourcepath on
xpg_echo off
これは上記の変数に追加され、同じ方法で復元できます。
$ oldstate="$oldstate;$(shopt -p)"
.
. # change options as needed.
.
$ eval "$oldstate"
バッシュのset -e
特別なケース
set -e
Bashでは、()の値がerrexit
サブシェル内でリセットされるため、set +o
$(...)サブシェル内でその値を取得することは困難です。
回避策として、次を使用します。
oldstate="$(set +o)"; [[ -o errexit ]] && oldstate="$oldstate; set -e"
または(ターゲットと競合せずにbashがそれをサポートしている場合)、このinherit_errexit
オプションを使用できます。
ノート:各シェルは設定または設定解除オプションのリストを少し異なって作成します(他のオプションが定義されていることは言うまでもありません)、文字列はシェル間で移植可能ではありませんが、同じシェルでは有効です。
zsh特別なケース
zsh
また、バージョン5.3(POSIX互換)からもうまく機能します。以前のバージョンでは、set +o
シェルにコマンドで再入力するのに適した形式でオプションを印刷するという点で、POSIXに部分的に従いました。置くオプション(印刷されません。未設定オプション)。
mksh特別なケース
mksh(および結果lksh)はまだこれを実行できません(MIRBSD KSH R54 2016/11/11)。 mksh マニュアルには次の内容が含まれています。
今後のリリースでは、set +oがPOSIX仕様で動作し、現在のオプションを復元するコマンドを印刷します。
答え2
Almquistシェルと派生(少なくとも dash
NetBSD / FreeBSD)と4.4以降では、オプションを関数のローカル(必要に応じてローカル変数の変数)に設定できます。sh
bash
local -
$-
$ bash-4.4 -c 'f() { local -; set -x; echo test; }; f; echo no trace'
+ echo test
test
no trace
これは以下には適用されません。源泉ファイルを上書きしてこの問題を解決できsource
ますsource() { . "$@"; }
。
を使用すると、ksh88
オプションの変更はデフォルトで機能別に行われます。の場合、ksh93
これは構文を使用して定義された関数でのみ発生しますfunction f { ...; }
(範囲指定は、ksh88を含む他のシェルで使用される動的スコープと比較して静的です)。
$ ksh93 -c 'function f { set -x; echo test; }; f; echo no trace'
+ echo test
test
no trace
次のオプションを使用してzsh
これを行います。localoptions
$ zsh -c 'f() { set -o localoptions; set -x; echo test; }; f; echo no trace'
+f:0> echo test
test
no trace
POSIXlyでは、次のことができます。
case $- in
(*x*) restore=;;
(*) restore='set +x'; set -x
esac
echo test
{ eval "$restore";} 2> /dev/null
echo no trace
ただし、一部のシェルは+ 2> /dev/null
復元時に出力します(追跡するcase
もちろん、set -x
設定がすでに有効になっている場合です。このメソッドは再入可能ではありません(自分を呼び出す関数や同じトリックを使用する他の関数で実行するのと同じ)。
バラよりhttps://github.com/stephane-chazelas/misc-scripts/blob/master/locvar.sh(POSIXシェル変数とオプションのローカルスコープ)この問題を解決するためにスタックを実装する方法を学びます。
すべてのシェルに対してサブシェルを使用してオプションの範囲を制限できます。
$ sh -c 'f() (set -x; echo test); f; echo no trace'
+ echo test
test
no trace
ただし、これはオプションだけでなく、すべて(変数、関数、エイリアス、リダイレクト、現在の作業ディレクトリ...)の範囲を制限します。
答え3
$-
最初に変数を読み込んで設定されて-x
いることを確認してから、変数に保存できます。
if [[ $- == *x* ]]; then
was_x_set=1
else
was_x_set=0
fi
~からバッシュマニュアル:
($-、ハイフン。)呼び出し時に指定された現在のオプションフラグ、組み込み設定によって設定されるか、シェル自体によって設定(例:-iオプション)に拡張されます。
答え4
確実にするために、set -x
これがスクリプト期間中に有効で一時テスト測定にすぎない場合(出力の永続的な部分ではない)、オプションを使用してスクリプトを呼び出します-x
。
$ bash -x path_to_script.sh
...またはオプションを追加してデバッグ出力を有効にするようにスクリプト(最初の行)を一時的に変更します-x
。
#!/bin/bash -x
...rest of script...
私はこれがあなたが望むものに比べて広すぎることを知っていますが(私の経験によると)、削除したい一時的なエントリでスクリプトを複雑にすることなくアクティブ/無効にする最も簡単で迅速な方法です。