Come posso modificare il comando shell corrente senza eseguirlo?


13

Sembra che ci siano molte informazioni su come modificare ed eseguire un comando usando l'editor usando "edit-and-execute-command (Cx Ce)", ma quello che vorrei ottenere è prendere il comando shell corrente, applicare alcuni filtri (usando uno script) e poi restituiscili per richiedere ulteriori modifiche manuali / di approvazione prima dell'esecuzione. Questo è possibile con bash?


Questa non è la risposta giusta alla domanda, ma prova a utilizzare il terminale ZSH invece del Bash nativo. Ha il completamento automatico, quindi non eseguire immediatamente i comandi. Ho provato personalmente questo scenario specifico e mi richiede sempre di premere Invio ogni volta che lo faccio edit-and-execute-command.
Praveen Premaratne,

1
La scorciatoia che funziona per me è Escape+ V, ma eseguirà comunque il comando. Per quanto riguarda la soluzione alternativa, aggiungerei echoin primo piano per eseguirlo stampando il comando sulla console per la revisione.
Kenorb,

2
puoi per favore fare un esempio concreto? Non capisco "applica un certo filtro (usando uno script) e poi lo restituisce al prompt".
Kent,

3
@PraveenPremaratne: zsh non è un terminale , è una shell .
Arkadiusz Drabczyk il

Risposte:


7

Ultimo aggiornamento sulla mia esperienza

La parte 0"+y$ddnella seguente mappatura è davvero qualcosa a cui dovresti pensare attentamente e adattarlo al tuo gusto / flusso di lavoro / esperienza.

Ad esempio, molto spesso mi sono ritrovato a finire con più righe nel buffer, dove voglio solo eseguire quello su cui si trova il cursore; in questo caso posso usare0"+y$dd:%d<CR> invece di 0"+y$dd.

E questo è solo uno dei possibili scenari.

Risposta finale per chi piace vim

Risposta originale

Ho spesso bisogno di fare lo stesso e lo faccio come segue. (Di solito uso set -o viin bash, quindi i punti 1 e 2 seguenti sono diversi se si utilizza set -o emacs, l'impostazione predefinita; in base alla domanda sembra che i punti 1 e 2 siano unificati in Ctrl+ xseguito da Ctrl+ e, che è più difficile da digitare, imho .)

  1. colpito Escapeper essere in modalità normale,
  2. colpire v per accedere all'editor per modificare il comando,
  3. modifica il comando come mi piace,

(Qui è dove fai la domanda.)

  1. colpire Escape0"+y$dd:wq,
    • Nota: 0"+y$non semplicemente "+yy, poiché quest'ultimo copierebbe anche la nuova riga e ciò comporterebbe l'esecuzione del comando dopo averlo incollato nella riga di comando,
  2. incolla gli appunti sulla riga di comando
    • come farlo dipende dal terminale che stai usando, immagino; Ho premuto Ctrl+ Alt+ vin URxvt.
  3. passare all'approvazione / modifica manuale.

Chiaramente questa è solo una soluzione alternativa, consistente nel copiare il comando modificato negli appunti prima di cancellare l'intero comando, in modo che nulla venga eseguito all'uscita dall'editor; tuttavia è il meglio che posso ottenere per me stesso.

Aggiornare

Poiché il mio EDITOR(e VISUAL) è uguale a vim, quando modifico il comando, lo modifico invim .

A questo proposito, ho notato che il buffer è chiamato /tmp/bash-fc.random, dove randomè una stringa casuale alfanumerica di 6 caratteri.

Questo dà spazio a molte possibilità, se si utilizza vimcome editor, in quanto è possibile definire alcune mappature nel proprio .vimrcper eseguire l'intera sequenza Escape0"+y$dd:wq. Ad esempio, un comando che useresti raramente durante la modifica di una riga di comando è Leaderd; quindi puoi inserire il seguente mapping nel tuo .vimrcfile

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

in modo che il passaggio 4 nella ricetta precedente diventi

  1. colpire EscapeLeaderd

Per me questo è il modo migliore per modificare i comandi
A.Villegas

2

Non è possibile farlo in Bash / readline ma è possibile in zsh usando il edit-command-linecomando:

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

Ora premi Control- x Control- eper aprire il tuo editor, modificare la riga, lasciare l'editor - vedrai la riga di comando aggiornata ma non verrà eseguita automaticamente.


1

Ora che ci penso, forse una variazione di ciò che @kenorb ha suggerito in un commento è la soluzione alternativa migliore (poiché sembra che non esista alcuna soluzione), se vogliamo attenerci bash .

Quello che puoi fare è anteporre a #(il carattere di commento in bash) al comando, piuttosto che echo. Quindi quando esci dall'exitor, il comando sarà inefficace e dovrai solo premere arrow up(o k, se lo usi set -o vi), rimuovere #e confermare.

Nota che questa strategia aggiunge solo pochi tasti, quindi può essere abbastanza efficiente, a seconda del tuo livello di digitazione.


1

Questi pezzi potrebbero avvicinarti:

a) sostituire l'associazione normale per newline newline (ctrl-M) bind -x '"\C-M":date"

b) afferrare la linea corrente dalla cronologia usando !#

sostituisci la data con qualunque script tu voglia.

c) modifica manualmente

d) se necessario, lega in qualche modo il !!:pquale stampa il nuovo comando sulla riga di comando ma non lo esegue, permettendoti così di modificarlo manualmente.

e) usando ctrl-J invia il comando modificato anziché una nuova riga

o potrebbero non ...


1

C'è un'opzione in bash per modificare il comando dalla cronologia senza eseguirlo. Non sono sicuro che sia possibile utilizzare lo script per questo, non sembra essere probabile. Tuttavia, è possibile apportare modifiche utilizzando i modificatori della cronologia.

  1. Abilita histverify opzione per impedire l'esecuzione del comando modificato
  2. Utilizzare la catena di modificatori per modificare l'ultimo comando
  3. Uso "!!" per mettere il risultato alla riga di comando per la modifica finale

Ecco come appare:

$ 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

1

Vorrei indicarti il framework Composure per Bash (non sono affiliato con esso): https://github.com/erichs/composure

Fornisce drafte revisefunzioni che sembrano aiutare a fare ciò che stai cercando di fare. Ecco una (lunga) citazione dal file Leggimi del progetto:

La compostezza aiuta permettendoti di disegnare rapidamente semplici funzioni di shell, suddividendo i tuoi lunghi filtri di pipe e comandi complessi in blocchi leggibili e riutilizzabili.

Prima bozza, fai domande più tardi

Una volta che hai creato la tua gemma di un comando, non gettarla via! Usa draft ()e dagli un buon nome. Questo memorizza l'ultimo comando come una funzione che è possibile riutilizzare in seguito. Pensalo come una bozza approssimativa.

  $ 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

Rivedi, rivedi, rivedi!

Ora che hai una funzione di shell minima, potresti volerlo migliorare attraverso il refactoring e la revisione. Usa il revise ()comando per rivedere la tua funzione shell nel tuo editor preferito.

  • generalizzare le funzioni con parametri di input
  • aggiungere o rimuovere funzionalità
  • aggiungere metadati di supporto per la documentazione

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

0

Non sembra possibile con una scorciatoia da tastiera, almeno:

$ 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.