Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 如何创建完整的三部分模式_Bash_Bash Completion - Fatal编程技术网

Bash 如何创建完整的三部分模式

Bash 如何创建完整的三部分模式,bash,bash-completion,Bash,Bash Completion,我有一个命令行工具,它以三部分的形式接受参数: $ t first_second_third 我有一组适用于第一个的有效值,一组适用于第二个的有效值,以及一组适用于第三个的有效值。我想使用Bash complete功能来完成选项值的每个部分,如下例所示: $ t [tab][tab] # shows options for first part walk run skip bike $ t w[tab] # completes first par

我有一个命令行工具,它以三部分的形式接受参数:

$ t first_second_third
我有一组适用于
第一个
的有效值,一组适用于
第二个
的有效值,以及一组适用于
第三个
的有效值。我想使用Bash complete功能来完成选项值的每个部分,如下例所示:

$ t [tab][tab]           # shows options for first part
walk run skip bike
$ t w[tab]               # completes first part and appends delimiter
$ t walk_[tab][tab]      # shows options for second part
home work park
$ t walk_h[tab]          # completes second part and appends delimiter
$ t walk_home_[tab][tab] # shows options for second part
morning afternoon evening
$ t walk_home_a[tab]     # completes second part and appends space
$ t walk_home_afternoon
我有以下代码:

_tool () {
  local cur="${COMP_WORDS[COMP_CWORD]}"

  local first="walk run skip bike"
  local second="home work park"
  local third="morning afternoon evening"

  case "${cur}" in
    *_*_*)
      COMPREPLY=( $(compgen -W "${third}" -- "") ); return 0;;
    *_*)
      COMPREPLY=( $(compgen -W "${second}" -S "_" -- ${cur}) ); compopt -o nospace; return 0;;
    *)
      COMPREPLY=( $(compgen -W "${first}" -S "_" -- ${cur}) ); compopt -o nospace; return 0;;
  esac
}

complete -F _tool t
第一条很有效;没什么特别的。但第二条没有给我选择权或完成权

$ t [tab][tab]
bike_  run_   skip_  walk_
$ t b[tab]
$ t bike_[tab][tab] # nothing but bells
$ t bike_[tab][tab]
home_  park_  work_
$ t bike_h[tab][tab]
home_  park_  work_
$ t bike_ho[tab][tab]
home_  park_  work_
我将第二个子句替换为以下内容(即,我在
COMPREPLY
调用中将
${cur}
替换为空字符串):

我在命令行上得到了所有选项的列表,但没有完成项

$ t [tab][tab]
bike_  run_   skip_  walk_
$ t b[tab]
$ t bike_[tab][tab] # nothing but bells
$ t bike_[tab][tab]
home_  park_  work_
$ t bike_h[tab][tab]
home_  park_  work_
$ t bike_ho[tab][tab]
home_  park_  work_
我认为可能与
${cur}
COMPREPLY
单词列表有一些不好的交互,因此我再次更改了第二个子句,添加了一个与当前单词的第一部分匹配的前缀:

local prefix=( $(expr "${cur}" : '\(.*_\)') )
COMPREPLY=( $(compgen -W "${second}" -P "${prefix}" -S "_" -- "") ); compopt -o nospace; return 0;;
这没有多大帮助。由于
${cur}
仍在
COMPREPLY
命令中,我再次没有选择或完成。使用空字符串,我得到了完整选项(而不仅仅是当前部分)。但是,按tab键将删除键入的内容

$ t bike_[tab][tab]
bike_home_  bike_park_  bike_work_
$ t bike_ho[tab]
$ t bike_ # "ho" was erased
当然,我对第三部分也有同样的问题

  • 如何让Bash一部分一部分地完成当前单词
  • 如何使Bash在选择选项之前不附加分隔符
  • 这与类似,但我不想列出所有可能的值排列,并且它们没有格式化为文件名(不确定文件名模式是否会产生差异)

    谢谢你的帮助

    --ap

    我能创造出你想要的东西。请参见下面的我的代码:

    _tool () {
      local cur="${COMP_WORDS[COMP_CWORD]}"
    
      local first="walk run skip bike"
    
      case "${cur}" in
        *_*_*)
          local firstsecond=`echo ${cur} | awk -F '_' '{print $1"_"$2}'`
          local third="${firstsecond}_morning ${firstsecond}_afternoon ${firstsecond}_evening"
          COMPREPLY=( $(compgen -W "${third}" -- ${cur}) ); return 0;;
        *_*)
          local firstcomp=`echo ${cur} | awk -F '_' '{print $1}'`
          local second="${firstcomp}_home ${firstcomp}_work ${firstcomp}_park"
          COMPREPLY=( $(compgen -W "${second}" -S "_" -- ${cur}) ); compopt -o nospace; return 0;;
        *)
          COMPREPLY=( $(compgen -W "${first}" -S "_" -- ${cur}) ); compopt -o nospace; return 0;;
      esac
    }
    
    complete -F _tool t
    
    我对autocomplete不太熟悉,这是我第一次使用
    compgen
    complete
    ,所以我不确定我是否能回答你关于这个理论的问题。我可以告诉你我做了什么,以防它有助于你理解这些糟糕的函数是如何工作的。 首先,我试着理解你所拥有的。我成功地再现了你的问题。然后我有了这样的想法,即使你不想自己在代码中列出每一个排列,我也可以使用局部变量来模拟,就像它有一样。我做的第一件事是在我们有了第一个下划线之后得到“first”元素,并将第二个元素添加到其中,然后将其提供给compgen。令我惊讶的是,它工作得很好。然后我试着对第三级做同样的事情。。。然后问题开始了。我发现第二部分没有我想象的那么好。完成第一个单词后,我会得到第二个单词的建议;在选择一个单词作为第二个单词并点击[TAB]后,第一个下划线将消失

    $ t [tab][tab]           # shows options for first part
    bike_ run_ skip_ walk_
    $ t w[tab]               # completes first part and appends delimiter
    $ t walk_[tab][tab]      # shows options for second part
    walk_home_ walk_park_ walk_work_
    $ t walk_h[tab]          # completes second part and appends delimiter
    $ t walk_home_[tab][tab] # screws up with it
    $ t walkhome_            
    
    我尝试将下划线移到awk中,但没有成功:

          local first=`echo ${cur} | awk -F '_' '{print $1"_"}'`
          local second="${first}home ${first}work ${first}park"
    
    出于某种原因,我不得不将变量名更改为与“first”不同的名称,它开始工作。然后,在第3个元素中,我遇到了与您上次描述的相同的问题,在第3个元素中键入的任何内容都将消失,但[tab][tab]将为我提供以下选项:

    $ t walk_home_[tab][tab] # shows options for second part
    morning afternoon evening
    $ t walk_home_aft[tab]     # erases what I typed
    $ t walk_home_
    

    在第三个单词中,我将
    ${cur}
    添加到compgen中,它成功了。这只是我所做的总结。。。但我有一个工作版本,所以我很满意。:-)

    我可以通过将特殊的
    $IFS
    变量设置为包含
    \uu
    字符来解决此问题?我需要试一试。嗨,亚历山大,看看下面我的答案,它应该很好用。我还添加了一个解释,以帮助您更好地理解它,因为我自己也不太理解它:DThanks,@msb。我会试一试,让你知道。bash completion是一个挑剔的野兽,有很多隐藏的陷阱,这就是为什么我使用bash completion框架,让你在yaml中定义你的完成层次,让框架为你解决复杂性