compgen warning: -C opção não funciona como eu esperava

3

Qual é a maneira correta de usar a opção compgen -C ?

Estou tentando aprender sobre a conclusão programável do Bash e, em particular, a função compgen builtin. Estou experimentando com as diferentes opções de linha de comando compgen e não entendo como o -C sinalizador deve funcionar. Do Manual de Referência do GNU Bash :

-C command

command is executed in a subshell environment, and its output is used as the possible completions.

Com base nisso, espero que algo como o seguinte funcione:

$ compgen -C 'echo "first_option second_option"' f
first_option

Mas em vez disso, eu entendo isso:

$ compgen -C 'echo "first_option second_option"' f
-bash: compgen: warning: -C option may not work as you expect
first_option second_option  f

Eu tentei isso com o Bash versão 4.2.45 no OS X 10.7 e com o Bash versão 4.2.25 no Ubuntu 12.04, e em ambos os casos recebi o mesmo erro:

-bash: compgen: warning: -C option may not work as you expect
    
por Curious Costanza 03.03.2014 / 22:05

1 resposta

2

Referindo-se novamente à página de manual bash:

When using the -F or -C options, the various shell variables set by the programmable completion facilities, while available, will not have useful values.

Eu assumo que este é o "comportamento inesperado" ao qual ele está se referindo. A falta de $COMP_WORDS e $COMP_CWORD no subshell criado por compgen significa que o seu "f" inicial não é passado para filtrar os resultados, daí as duas primeiras opções que você vê. O terceiro "f" - vou começar.

É ainda mais inesperado, à primeira vista, que parece não haver nenhuma maneira de suprimir essa saída (exceto a remoção de stderr) - mas, na verdade, há uma explicação razoável. Os argumentos devem ser usados contra o comando complete , com o qual compgen compartilha códigos e argumentos, e onde eles fazem mais sentido.

O comando complete é usado no registro de um comando de conclusão, por exemplo

complete -C /tmp/test.sh mycmd

E a fonte do bash (em pcompletion , gen_command_matches() ) explica como o entrou nos resultados:

/* [...]
 $0 == cs->command         (command to execute for completion list)
 $1 == command name        (command being completed)
 $2 = word to be completed (possibly null)
 $3 = previous word
 [...] */

O terceiro resultado em seu exemplo é, obviamente, a entrada de seu comando sendo passada de volta como argumento $2 . Usando a especificação de conclusão que criamos acima, podemos mostrar mais claramente como ela deve ser usada com um script que anota os argumentos:

 $ cat > /tmp/test.sh << EOF
 x=0
 for arg in $0 $@; do⋅
   echo "$x:$arg"; x=$[$x+1]
 done
 EOF

então:

 $ complete -C /tmp/test.sh mycmd
 $ mycmd prevarg curarg<tab><tab>
 0:/tmp/test.sh   1:mycmd   2:curarg   3:prevarg

Portanto, não é para dizer que -C não pode ser usado pelo compgen; só que você não está melhor do que com $() .

Eu suponho que a pergunta restante é: "por que -C e -F são definidos contra o compgen?" Eu não sei. Mais fácil, talvez; ou talvez os autores tenham decidido que um aviso (um tanto obscuro) era melhor do que simplesmente desabilitar o que poderia ser uma funcionalidade útil. A resposta, e provavelmente a coisa certa a fazer neste momento, é fazer um relatório de erros buscando esclarecimentos e / ou documentação aprimorada dos autores ...

    
por 14.04.2014 / 16:50