Como edito o comando shell atual sem executá-lo?

13

Parece haver muitas informações sobre como editar e executar um comando usando o seu editor usando "editar e executar o comando (Cx Ce)", mas o que eu gostaria de obter é usar o comando shell atual, aplique determinada filtragem (usando um script) e, em seguida, retorne-a para solicitar mais aprovação / alterações manuais antes da execução. Isso é possível com o bash?

Piotr Mazurek
fonte
Esta não é a resposta certa para a pergunta, mas tente usar o terminal ZSH em vez do Bash nativo. Possui preenchimento automático, portanto, não execute comandos imediatamente. Eu pessoalmente tentei esse cenário específico e sempre exige que eu pressione enter sempre que faço a edit-and-execute-command.
Praveen Premaratne 16/01
11
O atalho que funciona para mim é Escape+ V, mas ainda vai executar o comando. Quanto à solução alternativa, eu adicionaria echona frente para executá-lo imprimindo o comando no console para revisão.
kenorb 20/01
2
você pode fazer um exemplo concreto? Eu não entendo "aplique certa filtragem (usando um script) e, em seguida, retorne-a para solicitar".
Kent
3
@PraveenPremaratne: o zsh não é um terminal , é um shell .
Arkadiusz Drabczyk 21/01

Respostas:

7

Última atualização em minha experiência

A parte 0"+y$dddo mapeamento a seguir é realmente algo em que você deve pensar cuidadosamente e adaptá-lo ao seu gosto / fluxo de trabalho / experiência.

Por exemplo, com muita frequência me vi terminando com várias linhas no buffer, onde só quero executar a linha em que o cursor está; neste caso, eu posso usar em 0"+y$dd:%d<CR>vez de 0"+y$dd.

E este é apenas um dos cenários possíveis.

Resposta final para quem gosta vim

Resposta original

Costumo fazer o mesmo e faço o seguinte. (Normalmente eu uso o set -o viin bash, então os pontos 1 e 2 a seguir são diferentes se você usar set -o emacso padrão; com base na sua pergunta, parece que os pontos 1 e 2 estão unificados em Ctrl+ xseguido por Ctrl+ e, que é mais difícil de digitar, imho .)

  1. clique Escapepara estar no modo normal,
  2. pressione vpara entrar no editor para editar o comando,
  3. edite o comando como eu quiser,

(É aqui que você faz a pergunta.)

  1. bater Escape0"+y$dd:wq,
    • Nota: 0"+y$não apenas "+yyporque a última copia a nova linha também, e isso resultaria na execução do comando ao colá-lo na linha de comando,
  2. cole a área de transferência na linha de comando
    • como fazer isso depende do terminal que você está usando, eu acho; Eu apertei Ctrl+ Alt+ vdentro URxvt.
  3. prossiga para aprovação / edição manual.

Claramente, isso é apenas uma solução alternativa, consistindo em copiar o comando editado na área de transferência antes de excluir o comando inteiro, para que nada seja executado ao sair do editor; no entanto, é o melhor que posso obter para mim.

Atualizar

Como meu EDITOR(e VISUAL) é igual a vim, quando edito o comando, edito-o em vim.

A esse respeito, notei que o buffer é nomeado /tmp/bash-fc.random, onde randomé uma sequência aleatória alfanumérica de 6 caracteres.

Isso abre espaço para muitas possibilidades, se você usar vimcomo seu editor, pois poderá definir alguns mapeamentos .vimrcpara executar a sequência inteira Escape0"+y$dd:wq. Por exemplo, um comando que você raramente usaria ao editar uma linha de comando é Leaderd; portanto, você pode colocar o seguinte mapping no seu .vimrcarquivo

au BufEnter /tmp/bash-fc.* nn <Leader>d 0"+y$dd:wq<CR>

para que o passo 4 da receita acima se torne

  1. acertar EscapeLeaderd
Enrico Maria De Angelis
fonte
Para mim, esta é a melhor maneira de editar comandos
A.Villegas
2

Não é possível fazer isso no Bash / readline, mas é possível no zsh usando o edit-command-linecomando:

darkstar% autoload edit-command-line; zle -N edit-command-line
darkstar% bindkey "^X^E" edit-command-line

Agora pressione Control- x Control- epara abrir o editor, editar a linha, sair do editor - você verá a linha de comando atualizada, mas ela não será executada automaticamente.

Arkadiusz Drabczyk
fonte
1

Agora que penso sobre isso, talvez uma variação do que o @kenorb sugeriu em um comentário seja a melhor solução alternativa (como parece que não existe solução), se quisermos continuar bash.

O que você pode fazer é acrescentar um #(o caractere de comentário bash) ao comando, em vez de echo. Então, quando você sair do exitor, o comando será ineficaz e você precisará apenas pressionar arrow up(ou k, se você usar set -o vi), remover #e confirmar.

Observe que essa estratégia adiciona apenas algumas teclas, para que possa ser bastante eficiente, dependendo do seu nível de digitação.

Enrico Maria De Angelis
fonte
1

Essas peças podem aproximá-lo:

a) substitua a ligação normal pela nova linha nova (ctrl-M) bind -x '"\C-M":date"

b) pegue a linha atual do histórico usando !#

substitua a data pelo script que desejar.

c) editar manualmente

d) se necessário, de alguma forma, amarre o !!:pque imprime o novo comando na linha de comando, mas não o executa, permitindo a edição manual.

e) usando o comando ctrl-J submit editado em vez de uma nova linha

ou eles não podem ....

ShpielMeister
fonte
1

Existe uma opção no bash para modificar o comando do histórico sem executá-lo. Não sei se é possível usar o script para isso, não parece provável. Embora você possa fazer modificações usando modificadores de histórico.

  1. Ative a opção histverify para impedir a execução do comando modificado
  2. Use cadeia de modificadores para alterar o último comando
  3. Usar "!!" para colocar seu resultado na linha de comando para edição final

Aqui está como fica:

$ shopt -s histverify
$ ls *.sh
script1.sh  script2.sh  script3.sh  script-return.sh
$ !!:s/*/script1/:p
ls script1.sh
$ !!:s/1/2/:p
ls script2.sh
$ !!
$ ls script2.sh
script2.sh
Maxim Norin
fonte
1

Gostaria de apontar para o quadro de composição do Bash (não sou afiliado a ele): https://github.com/erichs/composure

Ele fornece drafte revisefunções que parecem ajudar no que você está tentando fazer. Aqui está uma citação (longa) do arquivo leia-me do projeto:

A composição ajuda a permitir que você rastreie rapidamente funções simples de casca, dividindo seus filtros de tubo longo e comandos complexos em pedaços legíveis e reutilizáveis.

Rascunho primeiro, faça perguntas depois

Depois de criar sua gema de comando, não a jogue fora! Use draft ()e dê um bom nome. Isso armazena seu último comando como uma função que você pode reutilizar mais tarde. Pense nisso como um rascunho.

  $ cat servers.txt
  bashful: up
  doc: down

  up-arrow

  $ cat servers.txt | grep down
  doc: down

  $ draft finddown

  $ finddown | mail -s "down server(s)" admin@here.com

Revise, revise, revise!

Agora que você possui uma função shell mínima, convém aprimorá-la através da refatoração e revisão. Use o revise ()comando para revisar sua função shell no seu editor favorito.

  • generalizar funções com parâmetros de entrada
  • adicionar ou remover funcionalidade
  • adicionar metadados de suporte para documentação

    $ revise finddown
    finddown ()
    {
      about finds servers marked 'down' in text file
      group admin
      cat $1 | grep down
    }
    
    $ finddown servers.txt
    doc: down
nwinkler
fonte
0

Não parece possível com um atalho de teclado, pelo menos:

$ bind -P | grep -e command -e edit
complete-command can be found on "\e!".
edit-and-execute-command can be found on "\C-x\C-e".
emacs-editing-mode is not bound to any keys
possible-command-completions can be found on "\C-x!".
vi-editing-mode is not bound to any keys
l0b0
fonte