bash中的转义斜线已完成

时间:2019-04-02 14:07:06

标签: bash autocomplete complete

我尝试使用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`中转义斜线。


评论评论:

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

1 个答案:

答案 0 :(得分:3)

如果您从-o filenames中删除了complete选项,则示例将按预期工作。由于补全不是文件名,这在一定程度上是有道理的。这是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)

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