3

我有一些冗长的脚本互相调用,我希望它们的输出更具描述性。这个想法是为每个脚本自定义 echo 命令,如下所示。

我的问题是,如何使它非递归,使用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仅适用于 shell 内部命令,例如echo. 我知道最初的问题与 相关echo,但由于这是“bash 覆盖功能”的热门谷歌热门,我想我会为其他命令添加我的解决方案。我正在编写一个包装器以在运行时更改终端名称ssh,因此我定义了一个名为的函数ssh,并且需要从内部调用实际的二进制文件。这可能不是最好的方法,但它可以做到:

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

我想出了 I/O 重定向作为解决方案。Bash Redirections Using Exec文章启发了我。它具有以下含义:

  • 重定向脚本的标准或错误输出,无论哪个命令打印到它,例如 echo、printf 等。
  • 子shell或源脚本没有重复的工作。
  • 重定向扩展到该脚本调用的任何可执行文件、其下标或源脚本。
  • 过滤器可以通过创建多个管道组成,其中一个管道将其输出重定向到下一个管道的输入,依此类推。

在我的bashshell 脚本中,我使用:

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别名用于sed逐行 ( .*) 过滤脚本的 I/O,该 I/O 会转到错误输出 ( 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. 等待sed由 2. 参数给出的 bash 作业标识的背景停止。

在我的主要功能开始时,我通常做 adeclare -r a="$(start_log_ctx)"并以stop_log_ctx_by_job "$a".

于 2012-11-04T12:18:50.920 回答