加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

bash和readline:在用户输入循环中的制表符完成?

发布时间:2020-12-15 20:05:34 所属栏目:安全 来源:网络整理
导读:我正在做一个bash脚本,向用户提供一个命令行。 cli代码如下: #!/bin/bashcmd1() { echo $FUNCNAME: "$@"}cmd2() { echo $FUNCNAME: "$@"}cmdN() { echo $FUNCNAME: "$@"}__complete() { echo $allowed_commands}shopt -qs extglobfn_hide_prefix='__'allow
我正在做一个bash脚本,向用户提供一个命令行。

cli代码如下:

#!/bin/bash

cmd1() {
    echo $FUNCNAME: "$@"
}

cmd2() {
    echo $FUNCNAME: "$@"
}

cmdN() {
    echo $FUNCNAME: "$@"
}

__complete() {
    echo $allowed_commands
}

shopt -qs extglob

fn_hide_prefix='__'
allowed_commands="$(declare -f | sed -ne '/^'$fn_hide_prefix'.* ()/!s/ ().*//p' | tr 'n' ' ')"

complete -D -W "this should output these words when you hit TAB"

echo "waiting for commands"
while read -ep"-> "; do
    history -s $REPLY
    case "$REPLY" in
        @(${allowed_commands// /|})?(+([[:space:]])*)) $REPLY ;;
        ?) __complete ;;
        *) echo "invalid command: $REPLY" ;;
    esac
done

澄清:在Bash 4中制作和测试

所以,“读-e”给出readline功能,我可以调用命令,编辑输入行等。我不能做任何方式是让readline的选项卡完成工作!

我试过两件事:

>应该如何应该做:使用bash内置“完整”和“compgen”,报告工作here更新:它不报告在脚本中工作。
> This ugly workaround

当在脚本中使用“完整”时,为什么readline不正确?它的工作原理,当我尝试从bash在交互模式…

在尝试我知道的自定义完成脚本(我每天使用它)并遇到相同的问题(当它类似于你的索引),我决定窥探通过bash 4.1源,并发现这个有趣的块bash -4.1 / builtins / read.def:edit_line():
old_attempted_completion_function = rl_attempted_completion_function;
rl_attempted_completion_function = (rl_completion_func_t *)NULL;
if (itext)
  {
    old_startup_hook = rl_startup_hook;
    rl_startup_hook = set_itext;
    deftext = itext;
  }
ret = readline (p);
rl_attempted_completion_function = old_attempted_completion_function;
old_attempted_completion_function = (rl_completion_func_t *)NULL;

看起来在readline()被调用之前,它会将完成函数重置为null,因为只有一个bash-hacking长胡子可能知道。因此,使用读取内置函数执行此操作可以简单地硬编码为禁用。

编辑:更多关于此:在读内置中停止完成的包装代码发生在bash-2.05a和bash-2.05b之间。我在该版本的bash-2.05b / CWRU / changelog文件中发现了此注释:

  • edit_line (called by read -e) now just does readline’s filename completion by setting rl_attempted_completion_function to NULL,since e.g.,doing command completion for the first word on the line wasn’t really useful

我认为这是一个遗留的监督,并且由于可编程完成已经走了很长的路,你在做什么是有用的。也许你可以让他们把它添加回来,或者只是补丁自己,如果这是可行的你正在做什么。

害怕我没有一个不同的解决方案,除了你到目前为止,但至少我们知道为什么它不工作与读。

编辑2:对,这里是一个补丁,我只是测试,似乎“工作”。通过所有单元和reg测试,并显示您的脚本使用修补的bash运行时的输出,如你所料:

$ ./tabcompl.sh
waiting for commands
-> **<TAB>**
TAB     hit     output  should  these   this    when    words   you
->

正如你将看到的,我只是注释掉这4行和一些计时器代码,以便在指定读-t时重置rl_attempted_completion_function,并且不再需要超时。如果你要发送Chet的东西,你可能希望先切除rl_attempted_completion_function垃圾,但这至少会让你的脚本正常运行。

补丁:

--- bash-4.1/builtins/read.def     2009-10-09 00:35:46.000000000 +0900
+++ bash-4.1-patched/builtins/read.def     2011-01-20 07:14:43.000000000 +0900
@@ -394,10 +394,12 @@
        }
       old_alrm = set_signal_handler (SIGALRM,sigalrm);
       add_unwind_protect (reset_alarm,(char *)NULL);
+/*
 #if defined (READLINE)
       if (edit)
        add_unwind_protect (reset_attempted_completion_function,(char *)NULL);
 #endif
+*/
       falarm (tmsec,tmusec);
     }

@@ -914,8 +916,10 @@
   if (bash_readline_initialized == 0)
     initialize_readline ();

+/*
   old_attempted_completion_function = rl_attempted_completion_function;
   rl_attempted_completion_function = (rl_completion_func_t *)NULL;
+*/
   if (itext)
     {
       old_startup_hook = rl_startup_hook;
@@ -923,8 +927,10 @@
       deftext = itext;
     }
   ret = readline (p);
+/*
   rl_attempted_completion_function = old_attempted_completion_function;
   old_attempted_completion_function = (rl_completion_func_t *)NULL;
+*/

   if (ret == 0)
     return ret;

请记住,修补的bash将不得不分发或提供某种程度上人们将使用您的脚本… …

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读