bashスクリプトには、log()
複数の場所で使用される関数とlogs()
多数の行をlog()
。set -x
logs()
log()
私は定義logs()
し、log()
少なくともその内容とせいぜい呼び出しまでもset -x
出力から抑制したいと思います。
答え1
関数内で関数が呼び出される方法を変更することはできませんが、サブシェルを呼び出す関数を定義できます。これにより、通常の中括弧の代わりに本文の周りに括弧が表示されます。
log() (
set +x
# rest of log()
)
その後、呼び出しは関数の残りの後続のコマンドではなく、呼び出しlog()
自体(既存のset -x
コードから)と呼び出しのみを生成します。この機能を終了すると、既存の設定が復元されます。set +x
set -x
答え2
すべてのシェルで動作する必要がある迅速で汚い方法は、関数ではlog
なく外部スクリプトを(一時的に)作成することです。
trap '...' DEBUG
Bashではを使用して結合することもできますshopt -s extdebug
。set -x
debug() {
local f=${FUNCNAME[1]} d=${#FUNCNAME[@]} c=$BASH_COMMAND
if [ "$NOTRACE" ]; then
case $debug_skip in ''|$d) debug_skip=;; *) return;; esac
eval "case \$c in $NOTRACE) debug_skip=\$d; return; esac"
fi
# before the 1st command in a function XXX
case $c in $f|"$f "*) return;; esac
printf >&2 "%*s(%s) %s\n" $((d * 2 - 4)) "" "$f" "$c"
}
(もちろん、奇妙な書式+インデントを捨ててそのまま作成することもできます。set-x
コマンドでstderrと混合するのではなく、別のファイルにリダイレクトすることもできます。)
それから:
NOTRACE='"log "*'
shopt -s extdebug
trap debug DEBUG
log(){ log1 "$@"; }; log1(){ log2 "$@"; }
log2(){ log3 "$@"; }; log3(){ echo "$@"; }
foo(){ foo1 "$@"; }; foo1(){ foo2 "$@"; }
foo2(){ foo3 "$@"; }; foo3(){ echo "$@"; }
bar(){ case $# in 0) ;; *) echo "$1"; shift; bar "$@";; esac; }
foo 1 2 3
log 7 8 9
bar 1 2 3 4
結果は次のとおりです。
(main) foo 1 2 3
(foo) foo1 "$@"
(foo1) foo2 "$@"
(foo2) foo3 "$@"
(foo3) echo "$@"
1 2 3
7 8 9
(main) bar 1 2 3 4
(bar) case $# in
(bar) echo "$1"
1
(bar) shift
(bar) case $# in
(bar) echo "$1"
2
(bar) shift
(bar) case $# in
(bar) echo "$1"
3
(bar) shift
(bar) case $# in
(bar) echo "$1"
4
(bar) shift
(bar) case $# in
答え3
xtrace出力を抑制するには、を使用しますset -x
。もう一度オンにするにはを使用しますset -x
。開いていることを確認するには、shopt -q -o xtrace
以下を使用してください。
log() {
if shopt -q -o xtrace; then TRACE_IS_ON=yes; else TRACE_IS_ON=no; fi
set +x # turn xtrace off
...
[[ "$TRACE_IS_ON" == "yes" ]] && set +x
}
まだ「ちょっとした会話」が少し残っていますが、それが私ができる最善です。 log() への呼び出しが表示されないようにするには、関数内部ではなく同様のコードで各 log() 呼び出しを囲むことができます。