1

我需要以编程方式确定 shell 别名在 bash 中解析为哪个命令;即,我需要编写一个 bash 函数,该函数将采用可能引用别名的名称并返回它最终引用的“真实”命令,并在适用的情况下通过别名链递归。

例如,给定以下别名:

alias dir='list -l'
alias list='ls'

我的功能在哪里dereference_alias

dereference_alias list    # returns "ls"
dereference_alias dir     # also returns "ls"

是否有一些我不知道的内置函数可以巧妙地做到这一点,还是我应该放弃自己的输出alias

4

2 回答 2

3

这是我编写的一个版本,它不依赖任何外部命令,并且还处理递归别名而不创建无限循环:

# Arguments:
#
#   $1  Command to compact using aliases
#
function command-to-alias()
{
    local alias_key
    local expansion
    local guess

    local command="$1"
    local search_again="x"
    local shortest_guess="$command"

    while [[ "${search_again:-}" ]]; do
        unset search_again
        for alias_key in "${!BASH_ALIASES[@]}"; do
            expansion="${BASH_ALIASES[$alias_key]}"
            guess="${command/#"$expansion"/$alias_key}"
            test "${#guess}" -lt "${#shortest_guess}" || continue
            shortest_guess="$guess"
            search_again="x"
        done
        command="$shortest_guess"
    done

    echo "$command"
}
于 2016-11-17T03:57:35.023 回答
1

这是我的做法,但我不确定这是最好的方法:

dereference_alias () {
  # recursively expand alias, dropping arguments
  # output == input if no alias matches
  local p
  local a="$1"
  if [[ "alias" -eq $(type -t $a) ]] && p=$(alias "$a" 2>&-); then
    dereference_alias $(sed -re "s/alias "$a"='(\S+).*'$/\1/" <<< "$p")
  else
    echo $a
  fi
}

这里的主要缺点是我依赖sed,并且我在别名中删除任何参数的方法在第一个空格处停止,期望别名永远不会指向由于某种原因在其名称中包含空格的程序(即alias badprogram='A\ Very\ Bad\ Program --some-argument') ,这是一个足够合理的假设,但仍然如此。我认为至少整个sed部分可以被一些利用 bash 自己的命令行解析/拆分/标记化的东西代替,但我不知道从哪里开始。

于 2013-01-06T09:40:03.790 回答