Ricorda un comando scritto a metà mentre controllo qualcosa


97

Mi trovo spesso nella seguente posizione: ho iniziato a digitare un comando lungo al prompt di bash, ma a metà strada scopro che devo controllare qualcosa con un altro comando. Questo è un problema quando sono alla console (no X), che è spesso il caso, perché allora ho solo i seguenti modi insoddisfacenti per farlo, che conosco:

  • Premi ctrl+ alt+ F2e accedi a un'altra console virtuale, e scopri cosa volevo, poi torna indietro e continua
  • ctrl+ a, digita echo + space+ enter, scopri cosa volevo, premi fino a quando non trovo il mio comando, ctrl+ a, delx 5, ctrl+ ee continua
  • Evidenzia ciò che ho digitato finora con il mouse (se gpm è in esecuzione, cosa che di solito è), premi ctrl+ cper interrompere, scopri cosa volevo facendo attenzione a non usare il mouse per evidenziare le cose, quindi premi il pulsante centrale del mouse su un nuovo prompt e continua
  • Prega gli dei della riga di comando che il comando scritto a metà non abbia effetti negativi ma semplicemente fallisca, e premi con cautela invio, quindi scopri cosa volevo, premi verso l'alto finché non ricevo il mio comando e continua
  • Salta nella mia macchina del tempo, viaggia indietro nel tempo e ricorda a me stesso di avviare la schermata prima di iniziare a digitare il comando, tornare indietro al presente, premere ctrl+ a c, scoprire cosa volevo, premere ctrl+ a ctrl+ae continuare

Quindi quello che voglio sapere è: esiste un modo più elegante per farlo? Una sorta di comando subshell o simile?

Sono più interessato ai metodi che non richiedono preparativi o impostazioni per funzionare.

Risposte:


68

Una versione un po 'più veloce di alex Ctrl + A Ctrl+ K(che si sposta in avanti sulla linea e poi taglia tutto in avanti) è semplicemente usare Ctrl+ U, che taglia indietro su bash e l'intera linea (indipendentemente dalla posizione corrente) su zsh. Quindi usi Ctrl+ Yper incollarlo di nuovo


1
Testando questo, concludo che Ctrl + U non si sposta indietro e taglia in avanti, ma piuttosto taglia indietro. Avere il cursore nel mezzo del comando lascia tutto ciò che c'è dietro nella riga di comando. Ancora un miglioramento del 33% rispetto alla soluzione di @ alex, dal momento che consente di risparmiare una sequenza di tasti.
Lauritz V. Thaulow,

2
@lazyr Oh, giusto; su di zshesso taglia l'intera linea, ma su di bashessa taglia all'indietro. Non ho mai notato questa differenza prima
Michael Mrozek

2
Oh, non sapevo che Ctrl + U metta anche del testo per uccidere il buffer. Bello sapere! :)
alex

1
^U ^Kavrà lo stesso effetto di ^A ^Kma è leggermente più ergonomico e significativamente più conveniente sotto screen.
intuito il

53

Fai ctrl-A per iniziare la riga, anteporre un hash e premere invio - in questo modo rimarrà nella cronologia dei comandi come un commento e potrai tornare ad esso con il cursore su

EDIT: ho appena notato che questa è una variante leggermente più elegante sul tuo # 2;)


1
Sì, e perché non ci ho pensato? Grazie!
Lauritz V. Thaulow,

1
Devo leggere prima di pubblicare la mia risposta. James ha ragione.
Sean C.

4
Si noti che questo non funzionerà in csho zshperché non consentono commenti nella shell interattiva. In zshè necessario attivare l'opzione corretta: setopt interactive_comments.
Sam Hocevar,

1
@Sam Sì, ma ": comando" ha lo stesso effetto (":" = comando nullo)
barrycarter

6
@barrycarter: no, :dovrebbe essere considerato dannoso per questo scopo e mai, mai suggerito. Eseguirà tutto dopo un punto e virgola, all'interno di backtick ecc. Con tutti gli effetti collaterali associati.
sam hocevar,

29

Premi Ctrl+A, Ctrl+Kper spostarti all'inizio della riga ed eliminare (uccidere) fino alla fine. Quindi fai le tue ricerche e, quando sei pronto per continuare, premi Ctrl+Y(strattona) per rimettere la linea salvata (uccisa).


3
Ah, ora è più simile a quello che avevo in mente. E lo faccio sempre in Emacs, avrei dovuto pensare di fare lo stesso sulla riga di comando.
Lauritz V. Thaulow,

13

In zsh, digito Ctrl+ Zper "sospendere" il comando che sto digitando e digitare un altro comando. Dopo aver eseguito quel comando (o interrotto con Ctrl+ C), il comando sospeso ritorna per l'edizione (anche ricordando la posizione del cursore). Come ulteriore comodità, se la riga di comando è vuota quando digito Ctrl+ Z, la chiave invoca invece il bgbuilt-in (quindi un doppio Ctrl+ Zinvia un comando in esecuzione direttamente in background).

fancy-ctrl-z () {
  emulate -LR zsh
  if [[ $#BUFFER -eq 0 ]]; then
    bg
    zle redisplay
  else
    zle push-input
  fi
}
zle -N fancy-ctrl-z
bindkey '^Z'          fancy-ctrl-z

Non so come fare qualcosa di simile in bash.

In qualsiasi shell, è possibile utilizzare il metodo a bassa tecnologia per aggiungere #a all'inizio della riga corrente .


2
la tua funzione è ammirevole, ma sapevi che zshha già una funzione per quella integrata ? Si chiama push-linee tutto ciò che devi fare è usare bindkeyper raggiungerlo.
Caleb,

@Caleb: non so perché lo uso push-inputpiuttosto che push-linequi, push-linesembra più appropriato (forse avevano solo le vecchie versioni di zsh push-input?). Ma questo non è un sostituto per il resto della funzione.
Gilles,

Per quanto ne so, l'unica differenza è lo stesso effetto vincolante sullo sfondo di un lavoro in esecuzione. Mi sto perdendo qualcosa?
Caleb,

1
@Caleb: No, è solo che trovo sia conveniente la combinazione dei due ( push-lineè inutile su una riga vuota, avere bgsu Ctrl+Zè utile solo quando ho appena sospeso quel processo con Ctrl+Z) e mnemonico (o sto facendo da sfondo al processo o la riga di comando parziale).
Gilles,

3
@Caleb push-inputsospende l'intero buffer di input, mentre push-linesospende solo la riga corrente. Se sto digitando un comando su più righe, voglio sospendere l'intero comando, così push-inputè quello giusto. Trovo push-inputpiù spesso utile di push-line(se voglio ritardare una riga in un buffer di input multilinea, posso semplicemente spostarmi all'inizio della riga e inserire una nuova riga), quindi in realtà mi chiedo perché abbia push-lineottenuto il keybinding predefinito e no push-input.
Gilles,

13

In bash, digita Alt+ #.

Quindi quando sei pronto, premi Upquindi Alt+ #.

Il primo inserisce #a all'inizio della riga per trasformarla in un commento, quindi accetta la riga, come se si fosse premuto Enter.

Quindi, quando lo fai una seconda volta, vede che la linea ha già una #a all'inizio, quindi la rimuove e la accetta, salvandoti di nuovo la Enterchiave.

Se la seconda volta ne inserisce un altro #, devi invece digitare Alt+ - Alt+ #.

Puoi fare in modo che zsh faccia lo stesso mettendo

bindkey -M emacs '\e#' pound-insert

nel tuo ~ / .zshrc.

Oppure, se si utilizzano i collegamenti vi, è possibile digitare #dalla modalità di comando sia in bash che in zsh.


2
Per me non funziona, il secondo comando significava rimuovere # # aggiunge solo # # in primo piano.
Lauritz V. Thaulow,

1
Il primo funziona? Quale versione di bash stai usando?
Mikel,

3
Alt + # funziona come descritto nel terzo paragrafo, ma non come nel quarto, semplicemente antepone un altro # in primo piano e accetta la riga. Uso bash 4.1.5 (1)-release su Ubuntu 10.10.
Lauritz V. Thaulow,

1
Oh caro, in bash richiede un argomento numerico, ad esempio Esc+1quindi Alt+ #per attivare / disattivare.
Mikel,

Funziona, ma è molto più ingombrante di un semplice Ctrl + A Del Ctrl + E, specialmente sul layout della mia tastiera in cui Alt + # è in realtà Alt + Maiusc + 3.
Lauritz V. Thaulow,

10

Una delle mie funzionalità preferite zshè la funzione push-line integrata che si occupa di questo senza nessuna delle attività di hacking in altre risposte qui. L'ho associato a Ctrl+ lnel mio .zshrcfile in questo modo:

bindkey '^L' push-line

Quindi quando sto digitando un comando e ho bisogno di fare qualcos'altro molto velocemente, posso invocarlo con un tasto e ottenere un prompt vuoto. Dopo aver eseguito l'altro comando, il prompt viene automaticamente compilato con quello che stavo scrivendo prima.

Puoi anche concatenare più livelli di questo e i comandi ti risponderanno in ordine inverso rispetto a quando li hai inseriti nella coda.


5
Legato a Ctrl+Qe ESC qdi default (in modalità emacs).
Gilles,

C'è qualcosa di simile per bash?
Magnus,

@Magnus: rivedi le altre risposte a questa domanda. Ci sono soluzioni per bash, ma non così eleganti.
Caleb,

@Caleb, avrei dovuto essere più specifico, esiste una combinazione di tasti singola simile per bash?
Magnus,

1
Questa è chiaramente la risposta "corretta", comunque per Zsh! Voglio solo menzionare il push-line-or-editwidget, che per impostazione predefinita non è associato a nessuna mappa di tasti. Al prompt di livello superiore fa la stessa cosa push-line, ma a qualsiasi livello di prompt in basso converte l'intero comando immesso in un buffer multilinea. Due fantastiche funzioni su un tasto! Posso raccomandare l'associazione push-line-or-editinvece che semplice push-line. Non perdi nulla e ottieni utili funzionalità.
wjv,

5

Oltre al trucco ctrl- a ctrl- k, se ti trovi sullo schermo, basta ctrl- a dper staccare e ricollegartiscreen -r

Puoi anche semplicemente aprire un'altra finestra con ctrl+a c


8
Se sei nella schermata, basta aprire un'altra finestra con Ctrl+A c.
Gilles,

1
@Gilles .. a meno che non sia necessario utilizzare alcuni aspetti dello stato della shell (variabili, funzioni, alias, ecc.).
intuito il

4

Un modo alternativo, anche se non perfetto, premere Ctrl-X Ctrl-E. Si aprirà l'editor predefinito contenente il comando mezzo digitato. Quindi puoi salvare il tuo comando in un file o aprire una nuova shell dal tuo editor. Quando si esce dalla nuova shell, si tornerà all'editor e il salvataggio dei contenuti li eseguirà automaticamente.

Questo non è perfetto perché non ti riporta alla shell originale, ma o forza l'esecuzione del comando o lo scarta completamente. Ma non ci sono selezioni temporanee o kill buffer di cui preoccuparsi, e ci sono anche alcune belle modifiche, ad esempio se editor = vi

:wq            # execute the command
:cq            # cancel and abort
:! command     # execute command
:shell         # open a new shell
:r filename    # insert the contents of a file for editing
:r ! command   # insert the output of a command for editing

Alternativa molto bella. Sono vi-emacs-agnostic, quindi sarò felice come un mollusco che usa questo quando i powertools sono davvero necessari. (A proposito di vi, ho provato l'emulatore Linux N64 Mupen64Plus qualche tempo fa. Esc ha abbandonato l'emulatore senza salvare. Presto ho rinunciato a giocare qualsiasi cosa.)
Lauritz V. Thaulow

1
@lazyr, per eseguire debian / ubuntu sudo update-alternatives --config editore scegliere il tuo editor preferito. Per altri sistemi imposta le variabili di ambiente EDITOR o VISUAL sul tuo editor preferito, ad esempio aggiungi il export EDITOR=/usr/bin/nanotuo .bashrc.
forcefsck

3

Simile al metodo di aggiunta #all'inizio della riga, esiste un metodo discutibilmente più semplice che utilizzo che non richiede il ritorno all'inizio della riga:

Basta aggiungere un preventivo aperto e non chiuderlo, sia singola o doppia.

Quindi premere Enter.

Quindi premere CtrlC.

Il comando parziale viene salvato nella cronologia dei comandi (disponibile tramite la freccia su) ma non viene effettivamente eseguito.


2

Usando zsh, se si digita <ESC> q(escape, quindi Q), la riga del prompt verrà tagliata, in modo da poter digitare un altro comando. Riceverai automaticamente il testo tagliato nel prompt successivo.

Può ricordare più righe contemporaneamente, quindi puoi usarlo mentre una riga ti sta aspettando. Puoi anche usarlo su una riga vuota per ritardare il ripristino della linea di taglio.

Non è il modo più efficiente se devi usare diversi comandi per il controllo / preparazione (dovrai digitare nuovamente <ESC> qprima di ogni comando). Ma penso che sia possibile associarlo a una scorciatoia più breve.


Se vuoi solo controllare il manuale, digita <ESC> h(escape, quindi H). Ciò eseguirà il run-helpbuilt-in, con la prima parola della riga di comando come argomento. Ritornerai intatta la tua riga una volta terminata.


La maggior parte dei terminal ti consentirà M-qinvece di<ESC> q
sleblanc il
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.