覆盖现有shell命令的最佳方法是什么?

时间:2018-06-18 18:03:40

标签: bash shell command-line zsh ping

如果有人需要修改现有的shell命令(内置或其他),那么最好的方法是什么?

让我说明我理解尝试这样的程序会涉及许多潜在的风险,但这就是我提出这个问题的原因。

我想创建一个shell函数(称为ping)来代替公共ping命令。为了这个主题,让我们说它至少应该在BashZsh shell环境中兼容。

具体来说,我想允许ping接受主机名中的完整URL(包含协议,尾随斜杠/路径名,查询参数等)。字符串操作不是让我感到困惑的,而是如何正确执行原始ping可执行文件而不调用除ping之外的函数。

例如 ,以下两个命令应该会产生相同的结果:

# EXAMPLE 2 (What `ping` will accept)
ping who.is

# EXAMPLE 1 (What I would like to be able to do with `ping`)
ping https://who.is/my/ping/?example=this

2 个答案:

答案 0 :(得分:3)

垫片可能如下所示(如果您的真实ping位于/usr/bin):

#!/usr/bin/env bash
uri_re='^[[:alnum:]]+://([^/]+)/'

if [[ $1 =~ $uri_re ]]; then
  exec /usr/bin/ping "${BASH_REMATCH[1]}" "${@:2}"
else
  exec /usr/bin/ping "$@"
fi

把它放在/opt/overrides/bin之类的地方,然后把它放在PATH中,而不是/usr/bin(所以PATH=/opt/overrides/bin:/bin:/usr/bin:/usr/local/bin等)。

或者,对于一个可以在所有符合POSIX的shell上运行的可移植函数(以及zsh,即使它不是一个):

ping() {
  local _ping_addr >/dev/null 2>&1 ||: "ignore failure on shells that don't support local"
  case $1 in
    *://*/)
      _ping_addr=${1#*://}
      _ping_addr=${_ping_addr%%/*}
      shift
      command ping "$_ping_addr" "$@"
      ;;
    *)
      command ping "$@" ;;
  esac
}

答案 1 :(得分:1)


以下功能可作为{{3}的 Mac Linux 上的嵌入式便携式外壳功能 },zshbash Shell环境。

“我想创建一个shell函数(称为ping以代替常见的sh命令。” { {3}}



# ---------------------------------------------------------
#  Better `ping` support for various URL formats/protocols
#
#  @param $1 - hostname
#
#  * Example Usage: `ping http://google.com/`
# ---------------------------------------------------------

function ping {
    local pingdomain="$1"
    shopt -s nocasematch # allow for lowercase
    pingdomain=${pingdomain/#*:\/\/} # strip leading protocol
    pingdomain=${pingdomain/#*:*@/} # strip leading user:pass@
    pingdomain=$(echo "${pingdomain//"?"//}") # remove '?' chars
    pingdomain="$(echo "$pingdomain" | cut -d/ -f 1)" # strip trailing '/' onwards
    echo "pinging hostname \"$pingdomain\"."
    command ping $pingdomain
}