冗長モードに冗長設定も設定している場合、xtrace 出力を改善するために PS4 を構成しようとしています。私がやりたいことのいくつかは、サブシェルを生成しますが、それらの操作の -x または -v の出力を見たいと思っています。
また、トレース出力を揃えるために、ネスティング/インダイレクションの深さレベル インジケーター (+) を削除したいと考えていました。
私の最初のアイデアは次のとおりでした。
BACKSPACES=$'\b\b\b\b\b\b\b\b'
PS4='+`printf "%s[\t] %-16.16s:%03d (%-16.16s) $ " ${BACKSPACES:0:$BASH_SUBSHELL} $(basename $BASH_SOURCE) $LINENO ${FUNCNAME[0]:+${FUNCNAME[0]}}`'
私が遭遇した最初の問題は、 $BASH_SUBSHELL が出力される + の数と常に同じであるとは限らないということでした。$SHLVL を調べても役に立ちませんでした。
echo $X
+ 0 2 $ echo x <-- toplevel prints one + and $BASH_SUBSHELL is 0, as expected
x
( echo subshell )
+ 1 2 $ echo subshell <-- $BASH_SUBSHELL increments to 1 as expected, but why only one + instead of two ++?
source ./test2.sh
+ 0 2 $ source ./test2.sh
echo $X$X$X$X
++ 0 2 $ echo xxxx <-- ??? is $BASH_SUBSHELL relative to the current file or something but the + indicators are not???
xxxx
subshell
$BASH_SUBSHELL の使用を忘れて、代わりに PS4 の最初の文字を印刷できない文字にすることで、これを回避できたと思いますが、それでも $BASH_SUBSHELL が期待どおりではない理由を知りたいです。
サブシェルが PS4 内で作成される問題を回避するために、PS1 の PROMPT_COMMAND に相当するものを調べましたが、自分で実装する方法に関するいくつかの指示以外は何も見つかりませんでした。
私が見つけた最善の方法は、DEBUG シグナルをトラップすることでした。
trap 'debugfun $BASH_SOURCE' DEBUG
もちろん、-vx オプションは debugfun の呼び出しにも適用されます。その出力を抑制するための私の解決策は、関数のステップを set +vx と set -vx でラップすることでした。
debugfun() {
set +vx
VAR=`basename $1 .sh`
set -vx
}
今...私はすべての呼び出し印刷の問題に対処しなければなりませんでした:
debugfun $BASH_SOURCE <-- from -v
++ debugfun ./test.sh <-- from -x
++ set +vx <-- from -x
-v が「set +vx」行にも出力しない理由はわかりません。-T オプションがそれを行うかもしれないと思ったが、そうではなかった。
とにかく、出力は常に一貫していると思っていたので、debugfun 内からこれらの 3 行を消去するだけで済みました。私の醜い解決策は、「set +vx」の後に次の行を追加することでした。
printf "\b\r\033[K\b\r\033[K\b\r\033[K" # clear previous 3 lines
出来た!
...複数回パイプする場合を除きます。
理由を示すために printf 行を削除します。
echo $X$X | sed 's/x/y/' # pipe once... debugfun is called every time before each pipe component
debugfun $BASH_SOURCE
++ debugfun ./test.sh
++ set +vx
debugfun $BASH_SOURCE
++ debugfun ./test.sh
++ set +vx
+ echo xx
+ sed s/x/y/
echo $X$X$X | sed 's/x/y/' | sed 's/y/x/' # pipe twice
debugfun $BASH_SOURCE
++ debugfun ./test.sh
++ set +vx
debugfun $BASH_SOURCE
++ debugfun ./test.sh
++ set +vx
+ echo xxx
+ sed s/x/y/ # because this line is here, clearing 3 previous lines from the next "set +vx" would clear it
debugfun $BASH_SOURCE
++ debugfun ./test.sh
++ set +vx
+ sed s/y/x/
xxx
最終的に、私はこの解決策を思いつきましたが、それは本当に醜いと思います。
SPACES=" "
PS4='^@\[\e[31m\]+ [\t] \
${SPACES:0:$((${#BASH_SOURCE} > 24 ? 0 : 24 - ${#BASH_SOURCE}))}${BASH_SOURCE:$((${#BASH_SOURCE} < 24 ? 0 : -24))}:\
${SPACES:0:$((3-${#LINENO}))}$LINENO \
${FUNCNAME:-${SPACES:0:20}}${FUNCNAME:+${SPACES:0:$((20 - ${#FUNCNAME}))}} \
$ \[\e[0m\]'
私が気に入らない主なことは、bash 文字列操作をネストして、$BASH_SOURCE を逆に切り捨てるだけでなく、サブシェルなしでベース名を取得できないことです (つまり、echo ${BASH_SOURCE##*/} と組み合わせます)。
私はアイデアがありません。私がやろうとしていることを達成する方法について、明確化またはヒントをいただければ幸いです。
GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)