所以我刚刚开始学习 bash 补全脚本,并开始为一个我经常使用的工具编写一个脚本。首先,我使用一组选项列表构建了脚本:
_zf_comp()
{
local cur prev actions
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
actions="change configure create disable enable show"
COMPREPLY=($(compgen -W "${actions}" -- ${cur}))
return 0
}
complete -F _zf_comp zf
这很好。接下来,我决定动态创建可用操作列表。我整理了以下命令:
zf | grep "Providers and their actions:" -A 100 | grep -P "^\s*\033\[36m\s*zf" | awk '{gsub(/[[:space:]]*/, "", $3); print $3}' | sort | uniq | awk '{sub("\-", "\\-", $1); print $1}' | tr \\n " " | sed 's/^ *\(.*\) *$/\1/'
它基本上做了以下事情:
- 抓取“提供商及其操作:”之后的“zf”命令中的所有文本
- 抓取所有以“zf”开头的行(我不得不在这里做一些花哨的工作,因为 ZF 命令以彩色打印)
- 抓住命令的第二部分并删除其中的所有空格(空格部分可能不再需要)
- 对列表进行排序
- 删除所有重复项
- 退出破折号(我在尝试调试问题时添加了它 - 可能不需要)
- 修剪所有新线
- 修剪所有前导和结尾空格
上述命令产生:
$ zf | grep "Providers and their actions:" -A 100 | grep -P "^\s*\033\[36m\s*zf" | awk '{gsub(/[[:space:]]*/, "", $3); print $3}' | sort | uniq | awk '{sub("\-", "\\-", $1); print $1}' | tr \\n " " | sed 's/^ *\(.*\) *$/\1/'
change configure create disable enable show
$
因此在我看来,它生成的字符串与我原始脚本中的字符串完全相同。但是当我这样做时:
_zf_comp()
{
local cur prev actions
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
actions=`zf | grep "Providers and their actions:" -A 100 | grep -P "^\s*\033\[36m\s*zf" | awk '{gsub(/[[:space:]]*/, "", $3); print $3}' | sort | uniq | awk '{sub("\-", "\\-", $1); print $1}' | tr \\n " " | sed 's/^ *\(.*\) *$/\1/'`
COMPREPLY=($(compgen -W "${actions}" -- ${cur}))
return 0
}
complete -F _zf_comp zf
我的自动完成功能开始出现问题。首先,它不会自动完成任何带有“n”的命令;其次,当它自动完成时(例如“zf create”),它不允许我在完成的命令上退格。
第一个问题让我完全不知所措。我认为第二个问题可能与彩色文本中的转义字符有关。
有什么想法吗?这让我抓狂了!
答案1
我发现有用的一件事是创建一个输出到另一个终端的调试功能:
debug() { echo "$@" >/dev/pts/0; }; export -f de
然后,您可以从完成函数内部使用变量内容等调用它,并且在测试时它不会干扰其自身的输出。
您可以尝试更改tr
为使用引号,看看是否能解决您的“n”问题:
tr '\n' ' '
grep
通过管道传输你的输出cat -v
来查看是否缺少任何转义序列。
此外,如果您可以避免调用那么多外部命令,它可能会加快速度。