【问题标题】:Escape slashes in bash completebash中的转义斜杠完成
【发布时间】:2019-04-02 14:07:06
【问题描述】:

我尝试使用 bash complete 内置命令来显示命令的不同选项。

当一个选项包含像-F/dev/null的路径时出现问题。

目前我正在使用

#!/bin/bash

_xyz-completion ()
{
  local cur

  COMPREPLY=()   # Array variable storing the possible completions.
  cur=${COMP_WORDS[COMP_CWORD]}

  case "$cur" in
    -*)
    COMPREPLY=( $( compgen -W "-oOption1 -F/dev/null" -- $cur ) )
    ;;
  esac

  return 0
}

complete -F _xyz-completion -o filenames xyz

如果-F 已经键入,则Tab 会成功完成。

但如果只输入了-,则会显示一个Tab

null       -oOption1

但我希望看到

-F/dev/null       -oOption1

我已经尝试过-F\/dev\/null-F//dev//null"-F/dev/null"-F\\\/dev\\\/null

这似乎只是一个显示问题,因为完成本身按预期工作。

我看不出如何适当地转义 `-F/dev/null` 中的斜线。


评论 cmets:

1)

没关系,如果将-F 替换为-Q 等非选项,也会有问题。 – 本杰明 W.

这不是问题,-F 看起来像是 complete 本身的一个选项,因为如果我将其更改为 xOPTION1 xF/dev/null,它甚至会失败

2)

我想知道 compgen -W "-oOption1 -F/dev/null" -- - 为您显示什么。

它显示(如预期)

-oOption1
-F/dev/null

如前所述,-F 成功完成到-F/dev/null

【问题讨论】:

  • 我认为斜线不是问题,但-Fcompgen 的有效选项。
  • 没关系,如果-F 被替换为非选项,例如-Q,也会有问题。
  • 我想知道compgen -W "-oOption1 -F/dev/null" -- - 会为您显示什么。
  • @Tanktalus 如果我只是以交互方式测试您的命令,它会显示预期的输出,没有被截断,但是当在问题中使用时,-F/dev 被截断。奇怪。
  • 如果您使用_xyz-completion () { COMPREPLY=(-oOption -F/dev/null); },我可以确认问题仍然存在。

标签: bash autocomplete bash-completion


【解决方案1】:

如果您从complete 中删除-o filenames 选项,您的示例将按预期工作。这是有道理的,因为完成不是文件名。这是 bash 版本 5.0.2(1)。

所以:

#!/bin/bash

_xyz-completion ()
{
  local cur

  COMPREPLY=()   # Array variable storing the possible completions.
  cur=${COMP_WORDS[COMP_CWORD]}

  case "$cur" in
    -*)
    COMPREPLY=( $( compgen -W "-oOption1 -F/dev/null" -- $cur ) )
    ;;
  esac

  return 0
}

complete -F _xyz-completion xyz

当有斜线时,它会截断部分完成,这绝对是一个错误。只有在显示选项时,实际完成才能正常工作。

编辑:

进一步研究后,filenames 选项用于转义可能包含空格或其他中断字符的字符串。基本上清理外壳的文件名。来自Programmable Completion Built-in man page

-o filenames:

告诉 Readline compspec 生成文件名,因此它可以执行任何特定于文件名的处理(例如在目录名中添加斜杠、引用特殊字符或禁止尾随空格)。此选项旨在与使用 -F 指定的 shell 函数一起使用。

显然这包括在最后一个斜杠之前和包括最后一个斜杠之前剥离所有内容。

EDIT2:

这是 bash 用于完成文件名的 readline 源代码中的注释。我从https://git.savannah.gnu.org/git/bash.git 的 bash 存储库中得到了这个。大师,所以在撰写本文时是 5.0 补丁 3。

./lib/readline/complete.c 第 697 行

/* Return the portion of PATHNAME that should be output when listing
   possible completions.  If we are hacking filename completion, we
   are only interested in the basename, the portion following the
   final slash.  Otherwise, we return what we were passed.  Since
   printing empty strings is not very informative, if we're doing
   filename completion, and the basename is the empty string, we look
   for the previous slash and return the portion following that.  If
   there's no previous slash, we just return what we were passed. */
static char *
printable_part (char *pathname)

对于文件名完成,它只想打印基本名称,最后一个斜杠之后的所有内容。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-07
    • 1970-01-01
    • 1970-01-01
    • 2015-09-22
    • 1970-01-01
    • 2017-10-17
    • 1970-01-01
    相关资源
    最近更新 更多