bash:個々の行を `-x`エコーからエスケープします


11

-xオプションで実行しているbashで、個々のコマンドのエコーを免除することはできますか?

私は出力をできるだけきれいにしようとしているので、のサブシェルでスクリプトの特定の部分を実行していset +xます。ただし、行set +x自体は引き続きエコーされ、出力に重要な情報は追加されません。

昔のことを覚えています。で.bat実行するとecho on、個々の行はで開始することで除外できました@。bashに相当するものはありますか?

#!/bin/bash -x

function i_know_what_this_does() {
  (
    set +x
    echo do stuff
  )
}

echo the next-next line still echoes 'set +x', is that avoidable?
i_know_what_this_does
echo and we are back and echoing is back on

上記を実行すると、出力は次のようになります。

+ echo the next-next line still echoes 'set +x,' is that 'avoidable?'
the next-next line still echoes set +x, is that avoidable?
+ i_know_what_this_does
+ set +x
do stuff
+ echo and we are back and echoing is back on
and we are back and echoing is back on

回答:


22

xtraceあなたがリダイレクトできるよう出力は、stderrに行くstderr/dev/null

i_know_what_this_does() {
  echo do stuff
} 2> /dev/null

関数内で実行されたコマンドのエラーを確認したい場合は、

i_know_what_this_does() (
  { set +x; } 2> /dev/null # silently disable xtrace
  echo do stuff
)

(...)代わりに{...}、サブシェルを介してその関数のローカルスコープを提供することに注意してください。bash、バージョン4.4は現在サポートしているためlocal -(と同様の機能のオプションは、ローカルにするためにAlmquistシェルのようset -o localoptionszsh、あなたが実行してサブシェルを避けることができるように、):

i_know_what_this_does() {
  { local -; set +x; } 2> /dev/null # silently disable xtrace
  echo do stuff
}

bash4.0から4.3 の代替方法は、$BASH_XTRACEFD変数を使用して、そのために専用のファイル記述子を開いて/dev/nullおくことです。

exec 9> /dev/null
set -x
i_know_what_this_does() {
  { local BASH_XTRACEFD=9; } 2> /dev/null # silently disable xtrace
  echo do stuff
}

以来bashとFDマークする能力を欠く近隣オンEXECしかし他のコマンドへのFD漏れの副作用を有しているフラグを、。

このlocvar.shも参照してください。このlocvar.shには、POSIXスクリプトで変数と関数のローカルスコープを実装するためのいくつかの関数が含まれており、それらをxtrace dにするかどうかを指定する関数trace_fnuntrace_fn関数も提供されています。


甘い!関数自体に適用できる修飾子があるかどうかを探していましたが、単純にstderrをリダイレクトすることは考えていませんでした。ありがとう!
2013年

1
ところで、同じページのstchaz.free.fr/which_interpreterはかなり素晴らしく、邪魔です。:-)
2013年

そして、私は2番目の方法であるここで再び戻ってきました。有用なstderr出力を消音せずにset + xを消音します。再度、感謝します!
2013年

2

set +x印刷される理由は、set -x実行する前に、実行しようとしているコマンドを展開して印刷します。そのため、シェルは、印刷しないことを伝える行を印刷するまで、印刷しないことを知りません。私の知る限りでは、それを止める方法はありません。


0

これがあなたが探していた解決策です:

function xtrace() {
  # Print the line as if xtrace was turned on, using perl to filter out
  # the extra colon character and the following "set +x" line.
  (
    set -x
    # Colon is a no-op in bash, so nothing will execute.
    : "$@"
    set +x
  ) 2>&1 | perl -ne 's/^[+] :/+/ and print' 1>&2
  # Execute the original line unmolested
  "$@"
}

元のコマンドは、恒等変換の下で同じシェルで実行されます。実行する直前に、引数の非再帰的なxtraceを取得します。これにより、すべての「echo」コマンドの複製コピーでstederrをスパムすることなく、気になるコマンドをxtraceできます。

# Example
echo "About to do something complicated ..."
xtrace do_something_complicated

または、回避するにはperl(および複数行コマンドの問題):+() { :;} 2> /dev/null; xtrace() { (PS4=; set -x; + "$@";{ set +x; } 2> /dev/null); "$@";}
StéphaneChazelas '27

いいえ、申し訳ありませんが、unix.stackexchange.com / a / 60049/17980が私が探していたソリューションです。:-) set -x操縦は私に比べて私に何かを買いますprintf >&2 '+ %s\n' "$*"か?
15

例:xtrace() { printf >&2 '+ %s\n' "$*"; "$@"; }
15
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.