Bash: Como enviar o comando para o próximo prompt para o usuário usar?

1

Em um script bash, eu quero produzir um comando no final, então o usuário só precisa pressionar Enter depois que meu script terminar para executar este comando.

Por exemplo o usuário precisa executar um comando com determinados parâmetros. Em vez de digitá-lo, meu script exibe o comando, com parâmetros para sua linha de comando e, em seguida, sai. Neste momento meu script está terminado. O usuário vê um novo prompt, com o comando "pré-escrito".

Esse gif deve dar uma ideia do que estou falando:

Euviessecomportamentoemváriosprogramascomo hstr e qfc , e eu acho que até mesmo o padrão reverse-i -search faz isso.

Pesquisei no Google tudo o que pude pensar, mas não consegui encontrar uma resposta.

    
por Lasse Meyer 02.10.2016 / 18:11

6 respostas

0

Se você estiver usando o X, a ferramenta xdotool pode ser uma solução, incluindo o script um comando como:

xdotool type command-line-to-display

Se o novo texto se misturar com a saída do script, algumas acrobacias podem ser necessário.

    
por 08.10.2016 / 19:49
3

Adicione estas linhas no final do seu script bash:

MY_COMMAND="ls"
MY_PARAMS=()
read -a MY_PARAMS -p $MY_COMMAND 
exec $MY_COMMAND ${MY_PARAMS[@]}

Isso pressupõe que o comando que você deseja executar seja ls , modifique-o como lhe convier. O que você digita é armazenado como um array chamado MY_PARAMS , inicializado pela primeira linha; o comando é então executado repetindo o comando seguido pela expansão da variável array, que significa todos os seus elementos. O acima é independente de quantos elementos você passa para o seu comando. O comando exec shell substitui o shell pelo comando fornecido, terminando efetivamente seu script.

EDITAR :

Se você quiser adicionar recursos completos de edição de comandos ao seu script, muito além do que read -e tem a oferecer, você pode fazer o seguinte: install rlwrap , adicione o seguinte código na parte inferior do seu script Bash:

stty -ixon
MYINPUT=()
HISTORY=$HOME/.bash_history
MYCOMMAND="ls"
MYINPUT=$(rlwrap -H $HISTORY -P $MYCOMMAND sh -c 'read REPLY && echo $REPLY')
stty ixon
exec sh -c "${MYINPUT[@]}"

rlwrap é um programa que é capaz de usar todos os recursos de readline , ao contrário da muito fraca opção Bash read -e . Ele permite que você especifique um arquivo onde procurar possíveis conclusões (usei o histórico do Bash, $ HOME / .bash_history inputrc em readline manual ) para que você possa escolher entre o estilo Emacs e a edição vi estilo, e permite que você procure por resultados em frente ( Ctrl r ) ou para trás ( Ctrl + s ) no arquivo de histórico, edite os comandos e muito mais.

Eu adicionei as opções stty -ixon / set ixon porque a maioria dos emuladores de terminal interceptam as seqüências de controle Ctrl + r e Ctrl + s , e assim por diante, e isso desabilita esse recurso por enquanto.

Além disso, o comando que você deseja (eu usei ls para propósitos ilustrativos) é pré-carregado e pode ser executado como é (atingindo retorno) ou modificado via os recursos readline de rlwrap .

O que o acima não pode fazer é exibir uma lista de possíveis correspondências, permitindo que você escolha por meio do seu teclado. Isto requer alguma programação BASH (veja a resposta do dirkt ).

    
por 02.10.2016 / 23:14
1

Não é uma resposta completa, mas uma explicação do que você viu:

Você pode dar uma olhada em como o qfc faz isso inspecionando qfc.sh . Ele usa recursos especiais de dois shells: Para zsh , o comando zle e para bash , a variável READLINE_LINE . Além disso, ambas as variantes usam uma função que é invocada dentro do shell, elas não apenas iniciam um script e disponibilizam essas informações na saída.

Fazê-lo de maneira independente da shell na saída de um script é um problema interessante. : -)

    
por 02.10.2016 / 19:23
0

pause ?

O Prompt de Comando no Windows tem o comando pause , que pode fazer o que você deseja realizar.

Ela exibe "Pressione qualquer tecla para continuar ...", mas sua saída pode ser evitada por pause > nul , que redireciona sua própria saída para em nenhum lugar em vez de na tela por padrão

    
por 02.10.2016 / 18:25
0

Aqui está uma pequena (, feia ?, buggy?) implementação com exemplo usando / para bash.

inline.sh:

inline () {
    stty_backup=$(stty -g)
    #I don't know why exactly, I just faced it
    stty sane
    res=$($READLINE_LINE 3>&1 >/dev/tty)
    stty $stty_backup
    READLINE_LINE=$res
    READLINE_POINT=${#READLINE_LINE}
}
#the bind is Alt-!, you can change it
bind -x '"\e!":"inline"'

hello.sh:

#!/bin/bash
echo Do you want:
echo 1 past?
echo 2 present?
echo 3 futur?

read -p "1 or 2 or 3? " r

if [ "$r" = "1" ]; then r="uptime"
elif [ "$r" = "2" ]; then r="date"
elif [ "$r" = "3" ]; then r="fortune fortunes"
else r=""
fi

echo $r >&3

Seu script precisa ser inteligente o suficiente, a string que você quer que seja retornada no seu prompt deve ser retornada através do fd 3 (veja inline.sh).

Agora,

source inline.sh

tipo

./hello.sh

pressione Alt -!

Você pode inserir inline.sh no seu bashrc, é claro.

    
por 11.10.2016 / 12:41
0

Solução alternativa:

na última linha do seu script você pode escrever algo como:

PrebuildCOMMAND="ls -lrt"             # just as example
echo "That's your command "           # keep your user informed
read -e -p " " -i "$PrebuildCOMMAND"  CMDtoEXECUTE
$CMDtoEXECUTE                         # here you execute what it was answered

Observação: só agora notei que essa é uma variante (simplificada) do que foi proposto por outra resposta (mais completa ).

    
por 12.10.2016 / 12:12