你不能改变从函数内部调用函数的方式,但你可以定义函数来调用一个子shell,然后立即关闭跟踪;注意身体周围的括号而不是典型的大括号:
log() (
set +x
# rest of log()
)
Run Code Online (Sandbox Code Playgroud)
log()
然后调用只生成调用本身(来自现有set -x
代码)和set +x
调用,而不是函数中的其余后续命令。set -x
功能退出后,将恢复现有设置。
小智 3
一个应该在所有 shell 中都有效的快速而肮脏的技巧是(暂时)使您的log
外部脚本而不是函数。
在 bash 中,您还可以使用trap '...' DEBUG
和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"
}
Run Code Online (Sandbox Code Playgroud)
(当然,您可以放弃奇怪的格式+缩进,使其完全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
Run Code Online (Sandbox Code Playgroud)
将导致:
(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
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
523 次 |
最近记录: |