我需要以编程方式确定shell别名在bash中解析为哪个命令;即,我需要编写一个bash函数,该函数将使用一个可能引用别名的名称,并返回它最终引用的“真实”命令,在适用的情况下通过别名链递归。
例如,给定以下别名:
alias dir='list -l'
alias list='ls'
我的函数是dereference_alias
,
dereference_alias list # returns "ls"
dereference_alias dir # also returns "ls"
是否有一些内置我不知道这样做是否整齐,或者我是否应该自己去抓取alias
的输出?
答案 0 :(得分:2)
这是我编写的一个版本,它不依赖于任何外部命令,也可以在不创建无限循环的情况下处理递归别名:
# 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"
}
答案 1 :(得分: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自己的命令行解析/拆分/标记化的东西取代,但我不知道从哪里开始。