我有环境变量$SCRIPT
。通常我可以使用自动完成
vim $SC<tab>
并按预期完成工作。在某些系统上它不起作用。我已加载 bash 补全,但在这些情况下补全仅适用于目录(cd $SCRIPT_DIREC<tab>
正在工作)。
主要是我对 bash 4.2 有问题。
什么shopt
可以启用它?
编辑:我将我的shopt
设置与正常工作的 Bash 4.3 和不工作的 Bash 4.2(Ubuntu 服务器 12.04)进行了比较,几乎没有什么区别(大多数是 4.3 特定的),将其余设置相同,但没有任何效果。
答案1
问题具体在于 shell 内置命令可以<tab>
扩展参数名称,但外部命令则不能。这就是为什么cd
有效。 echo
、read
和任何其他内置函数继续像 OP 期望的那样工作。
与商店无关。
它位于 bash_completion 库中(/etc/bash_completion
在我的 12.04.4 系统中)。版本 1.3 中存在导致此故障情况的某些内容。在 1.99 或之前的某个地方它被修复了。
如果bash_completion 库存~/.bash_completion
在,它会自动获取源代码,因此我建议创建一个包含以下内容的文件,以重载 12.04.4 库中不适合您的函数定义。我做了一些小测试,但我使用的任何机器都没有受到这种情况的影响,所以买者自负。
# following functions are direct copy/pastes from
# bash_completion RELEASE: 1.99
# overloading `_longopt()' and adding `_variables()' and `_init_completion()'
# appears to be all that is needed to correct this.
#
# http://unix.stackexchange.com/questions/126300/bash-autocomplete-variables-for-other-commands-than-cd
_init_completion()
{
local exclude= flag outx errx inx OPTIND=1
while getopts "n:e:o:i:s" flag "$@"; do
case $flag in
n) exclude+=$OPTARG ;;
e) errx=$OPTARG ;;
o) outx=$OPTARG ;;
i) inx=$OPTARG ;;
s) split=false ; exclude+== ;;
esac
done
# For some reason completion functions are not invoked at all by
# bash (at least as of 4.1.7) after the command line contains an
# ampersand so we don't get a chance to deal with redirections
# containing them, but if we did, hopefully the below would also
# do the right thing with them...
COMPREPLY=()
local redir="@(?([0-9])<|?([0-9&])>?(>)|>&)"
_get_comp_words_by_ref -n "$exclude<>&" cur prev words cword
# Complete variable names.
_variables && return 1
# Complete on files if current is a redirect possibly followed by a
# filename, e.g. ">foo", or previous is a "bare" redirect, e.g. ">".
if [[ $cur == $redir* || $prev == $redir ]]; then
local xspec
case $cur in
2'>'*) xspec=$errx ;;
*'>'*) xspec=$outx ;;
*'<'*) xspec=$inx ;;
*)
case $prev in
2'>'*) xspec=$errx ;;
*'>'*) xspec=$outx ;;
*'<'*) xspec=$inx ;;
esac
;;
esac
cur="${cur##$redir}"
_filedir $xspec
return 1
fi
# Remove all redirections so completions don't have to deal with them.
local i skip
for (( i=1; i < ${#words[@]}; )); do
if [[ ${words[i]} == $redir* ]]; then
# If "bare" redirect, remove also the next word (skip=2).
[[ ${words[i]} == $redir ]] && skip=2 || skip=1
words=( "${words[@]:0:i}" "${words[@]:i+skip}" )
[[ $i -le $cword ]] && cword=$(( cword - skip ))
else
i=$(( ++i ))
fi
done
[[ $cword -eq 0 ]] && return 1
prev=${words[cword-1]}
[[ ${split-} ]] && _split_longopt && split=true
return 0
}
_variables()
{
if [[ $cur =~ ^(\$\{?)([A-Za-z0-9_]*)$ ]]; then
[[ $cur == *{* ]] && local suffix=} || local suffix=
COMPREPLY+=( $( compgen -P ${BASH_REMATCH[1]} -S "$suffix" -v -- \
"${BASH_REMATCH[2]}" ) )
return 0
fi
return 1
}
_longopt()
{
local cur prev words cword split
_init_completion -s || return
case "${prev,,}" in
--help|--usage|--version)
return 0
;;
--*dir*)
_filedir -d
return 0
;;
--*file*|--*path*)
_filedir
return 0
;;
--+([-a-z0-9_]))
local argtype=$( $1 --help 2>&1 | sed -ne \
"s|.*$prev\[\{0,1\}=[<[]\{0,1\}\([-A-Za-z0-9_]\{1,\}\).*|\1|p" )
case ${argtype,,} in
*dir*)
_filedir -d
return 0
;;
*file*|*path*)
_filedir
return 0
;;
esac
;;
esac
$split && return 0
if [[ "$cur" == -* ]]; then
COMPREPLY=( $( compgen -W "$( $1 --help 2>&1 | \
sed -ne 's/.*\(--[-A-Za-z0-9]\{1,\}=\{0,1\}\).*/\1/p' | sort -u )" \
-- "$cur" ) )
[[ $COMPREPLY == *= ]] && compopt -o nospace
elif [[ "$1" == @(mk|rm)dir ]]; then
_filedir -d
else
_filedir
fi
}
答案2
一种方法是,您只需将其别名设置为
alias Script="<Your $Script Here>"
在您的用户的 .profile 中/home/user/.profile
,然后使用以下命令获取它:
$ . profile
然后检查它是否自动完成。