3

相互に呼び出す長いスクリプトがいくつかあり、それらの出力をより説明的にしたいと考えています。アイデアは、以下のようなもので各スクリプトのエコー コマンドをカスタマイズすることです。

私の質問は、echo?を使用して非再帰的にする方法です。

これはscript1.shです

#!/bin/bash
#Original version:
#function echo(){ echo $(basename $0 .sh): $1; }
#Version after fixes
function echo(){ builtin echo -n "$(basename $0 .sh): ">&2; builtin echo $@ ; } 
echo Info
./script2.sh

これはscript2.shです

#!/bin/bash
#Original version:
#function echo(){ echo $(basename $0 .sh): $1; }
#Version after fixes
function echo(){ builtin echo -n "$(basename $0 .sh): ">&2; builtin echo $@ ; } 
echo Info
exit 0

したがって、出力は次のようになります。

>./script1.sh
script1: Info
script2: Info

- - 編集

ボーナス:

>./script1.sh 2> /dev/null 
Info
Info
4

3 に答える 3

13

builtinキーワードを使用します:

function echo(){ builtin echo $(basename $0 .sh): $1; }

ここにヘルプページがあります:

$ help builtin
builtin: builtin [shell-builtin [arg ...]]
    Execute shell builtins.

    Execute SHELL-BUILTIN with arguments ARGs without performing command
    lookup.  This is useful when you wish to reimplement a shell builtin
    as a shell function, but need to execute the builtin within the function.

    Exit Status:
    Returns the exit status of SHELL-BUILTIN, or false if SHELL-BUILTIN is
    not a shell builtin..
于 2011-12-03T22:33:05.827 に答える
1

builtinのようなシェル内部コマンドでのみ機能しますecho。元の質問が具体的にはecho. 実行時に端末名を変更するラッパーを作成しているsshので、呼び出される関数を定義し、その中sshから実際のバイナリを呼び出す必要があります。最善の方法ではないかもしれませんが、次のようにするとうまくいきます。

function ssh {
    $(which ssh) $@
}
于 2015-03-04T16:40:31.677 に答える
0

解決策として I/O リダイレクトを思いつきました。Exec を使用したBash リダイレクトの記事は、私にインスピレーションを与えました。これには次の意味があります。

  • echo、printf など、どのコマンドがスクリプトに出力されても、スクリプトの標準出力またはエラー出力をリダイレクトします。
  • サブシェルまたはソース スクリプトの反復作業はありません。
  • リダイレクションは、このスクリプト、サブスクリプト、またはそのソース スクリプトによって呼び出されているすべての実行可能ファイルに適用されます。
  • フィルターは、1 つのパイプがその出力を次のパイプの入力にリダイレクトするなど、いくつかのパイプを作成することによって構成できます。

私のbashシェルスクリプトでは、次を使用します。

alias start_log_ctx="start_filter_by_pipe_regex 2 s/.*/${0##*/}\(pid=$$\): \0/"
function start_filter_by_pipe_regex {
  declare -r a="$(mktemp -u)" #1
  mknod "$a" p                #2
  sed <"$a" ">&$1" "$2" &     #3
  exec "$1">"$a"              #4
}

alias stop_log_ctx_by_job="stop_filter_by_pipe_job 2"
def stop_filter_by_pipe_job {
  exec "$1">&- #1
  wait "$2" #2
}

本質的に、start_log_ctxエイリアスは、エラー出力に送られるスクリプトの I/Osedを行ごとに ( .*) フィルター処理し ( 2)、スクリプトのベース名 ( ${0##*/}) とプロセス ID ( pid=$$) を各行の先頭に追加するために使用します。このstart_filter_by_pipe_regex関数は次のように機能します。

  1. 絶対パスを-U保存しますが、一時ファイルを作成 ( ) しません。
  2. [1.]の絶対パスの下にパイプを作成します。
  3. sedバックグラウンドでフィルターとして開始します ( &)。[2.] のパイプから読み取り ( )、標準出力 ( ) を 1. パラメーターとして指定されたファイル記述子に<リダイレクトします。>2. パラメータとして指定されたフィルタを に渡しますsed
  4. >1. パラメータとして与えられたファイル記述子を [2.] のパイプにリダイレクト ( ) します。

stop_log_ctxエイリアスは、エラー出力のファイル記述子 ( ) を閉じ、以前2に開始された が停止するのを待ちsedます。ファイル記述子を閉じると、暗黙的にこれが行われます。このstop_filter_by_pipe_job関数は次のことを行います。

  1. 1. パラメータとして指定されたファイル記述子を閉じて、 を停止しsedます。
  2. sed2. パラメーターとして指定された bash ジョブによって識別されるバックグラウンドが停止するまで待ちます。

メイン関数の最初に、通常は aを実行し、declare -r a="$(start_log_ctx)"で終了しstop_log_ctx_by_job "$a"ます。

于 2012-11-04T12:18:50.920 に答える