Denken Sie an einen halb getippten Befehl, während ich etwas überprüfe

97

Ich befinde mich oft in der folgenden Position: Ich habe begonnen, einen langen Befehl an der Bash-Eingabeaufforderung einzugeben, aber nach der Hälfte der Zeit muss ich herausfinden, dass ich etwas mit einem anderen Befehl überprüfen muss. Dies ist ein Problem, wenn ich an der Konsole bin (kein X), was häufig der Fall ist, da ich dann nur die folgenden unbefriedigenden Möglichkeiten habe, dies zu tun, die mir bekannt sind:

  • Drücken Sie ctrl+ alt+ F2und melden Sie sich an einer anderen virtuellen Konsole an, und finden Sie heraus, was ich wollte. Gehen Sie dann zurück und fahren Sie fort
  • ctrl+ a, tippe echo + space+ enter, finde heraus, was ich wollte, drücke bis ich meinen Befehl finde, ctrl+ a, delx 5, ctrl+ eund fahre fort
  • Markieren Sie, was ich bisher mit der Maus eingegeben habe (wenn gpm ausgeführt wird, was normalerweise der Fall ist), drücken Sie ctrl+ c, um die Eingabe zu unterbrechen, und finden Sie heraus, was ich wollte Klicken Sie auf eine neue Eingabeaufforderung und fahren Sie fort
  • Bete an die Befehlszeilengötter, dass der halb geschriebene Befehl keine nachteiligen Auswirkungen hat, sondern einfach fehlschlägt. Drücke vorsichtig die Eingabetaste, finde dann heraus, was ich wollte, drücke den oberen Pfeil, bis ich meinen Befehl wieder erhalte, und fahre fort
  • Springe in meine Zeitmaschine, reise zurück in die Zeit und erinnere mich daran, den Bildschirm zu starten, bevor ich mit der Eingabe von Befehlen beginne, gehe zurück in die Gegenwart, drücke ctrl+ a c, finde heraus, was ich wollte, drücke ctrl+ a ctrl+aund fahre fort

Was ich wissen möchte ist, gibt es eine elegantere Art, dies zu tun? Eine Art Subshell-Befehl oder ähnliches?

Ich interessiere mich am meisten für Methoden, die keine Vorbereitung oder Einrichtung erfordern, um zu funktionieren.

Lauritz V. Thaulow
quelle

Antworten:

68

Eine etwas schnellere Version von alex Ctrl + A Ctrl+ K(denen die Vorderseite der Linie bewegt und schneidet dann alles nach vorne) ist nur zu verwenden Ctrl+ U, die rückwärts auf bash schneidet, und die gesamte Zeile (unabhängig von Ihrer aktuellen Position) auf zsh. Dann verwenden Sie Ctrl+, Yum es erneut einzufügen

Michael Mrozek
quelle
1
Wenn ich das teste, komme ich zu dem Schluss, dass Strg + U nicht vor- und zurückbewegt, sondern rückwärts schneidet. Wenn sich der Cursor in der Mitte des Befehls befindet, wird alles, was dahinter steht, in der Befehlszeile angezeigt. Trotzdem eine Verbesserung von 33% gegenüber der Lösung von @ alex, da ein Tastendruck eingespart wird.
Lauritz V. Thaulow
2
@lazyr Oh, ganz richtig; auf zshsie die gesamte Linie nicht schneidet, sondern bashschneidet sie nach hinten. Ich habe diesen Unterschied noch nie bemerkt
Michael Mrozek
2
Oh, ich wusste nicht, dass Strg + U auch Text in den Puffer bringt. Gut zu wissen! :)
alex
1
^U ^Khat den gleichen Effekt wie ^A ^K, ist aber geringfügig ergonomischer und deutlich bequemer unter screen.
Intuited
53

Drücken Sie Strg-A, um zum Zeilenanfang zu gelangen, stellen Sie einen Hash voran und drücken Sie die Eingabetaste. Auf diese Weise bleibt er als Kommentar im Befehlsverlauf und Sie können mit dem Cursor nach oben dorthin zurückkehren

BEARBEITEN: habe gerade bemerkt, dass dies eine etwas elegantere Variante auf deiner # 2 ist;)

jamespo
quelle
1
Ja, und warum habe ich nicht daran gedacht? Danke!
Lauritz V. Thaulow
1
Ich muss lesen, bevor ich meine eigene Antwort poste. James hat es richtig drauf.
Sean C.
4
Beachten Sie, dass dies in cshoder nicht funktioniert, zshda Kommentare in der interaktiven Shell nicht zulässig sind. In zshSie müssen die richtige Option aktivieren: setopt interactive_comments.
Sam Hocevar
1
@ Sam Ja, aber ": Befehl" hat den gleichen Effekt (":" = der Null-Befehl)
Barrycarter
6
@barrycarter: nein, :sollte für diesen Zweck als schädlich angesehen und niemals vorgeschlagen werden. Es wird alles nach einem Semikolon, in Backticks usw. mit allen damit verbundenen Nebenwirkungen ausgeführt.
Sam Hocevar
29

Drücken Sie Ctrl+A, Ctrl+Kum an den Zeilenanfang zu gelangen und bis zum Ende zu löschen (töten). Dann recherchieren Sie, und wenn Sie bereit sind, weiterzuschlagen Ctrl+Y, um Ihre gerettete (getötete) Linie zurückzusetzen.

Alex
quelle
3
Ah, jetzt ist das eher so, wie ich es mir vorgestellt habe. Und ich mache das die ganze Zeit in Emacs, hätte darüber nachdenken sollen, dasselbe auf der Kommandozeile zu tun.
Lauritz V. Thaulow
13

In zsh gebe ich Ctrl+ ein Z, um den Befehl, den ich eingebe, auszusetzen und einen anderen Befehl einzugeben. Nachdem ich diesen Befehl ausgeführt habe (oder ihn mit Ctrl+ abgebrochen habe C), wird der angehaltene Befehl zur Bearbeitung zurückgegeben (auch wenn ich mich an die Cursorposition erinnere). Wenn die Befehlszeile bei der Eingabe von Ctrl+ leer ist Z, ruft die Taste bgstattdessen die integrierte Funktion auf (ein doppeltes Ctrl+ Zsendet also einen ausgeführten Befehl direkt in den Hintergrund).

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

Ich weiß nicht, wie ich etwas Ähnliches in Bash machen soll.

In jeder Shell können Sie die Low-Tech-Methode zum Hinzufügen von a #am Anfang der aktuellen Zeile verwenden .

Gilles
quelle
2
Ihre Funktion ist bewundernswert, aber wussten Sie, dass bereits zsheine Funktion dafür eingebaut ist ? Es heißt push-lineund alles, was Sie tun müssen, ist es zu benutzen bindkey, um es zu erreichen.
Caleb
@Caleb: Ich weiß nicht, warum ich das push-inputeher benutze als push-linehier, push-linescheint das passender zu sein (vielleicht hatten nur alte Versionen von zsh push-input?). Dies ist jedoch kein Ersatz für den Rest der Funktion.
Gilles
Soweit ich das beurteilen kann, ist der einzige Unterschied der gleiche Bindungseffekt zum Hintergrund eines laufenden Jobs. Vermisse ich etwas?
Caleb
1
@Caleb: Nein, es ist nur , dass ich die Kombination der beiden finden sowohl bequem ( push-lineist nutzlos auf eine leere Zeile, mit bgauf Ctrl+Znur sinnvoll ist , wenn ich nur diesen Prozess mit suspendiertem haben Ctrl+Z) und mnemonic (Ich bin entweder Hintergrund versetzen, den Prozess oder die teilweise Befehlszeile).
Gilles
3
@Caleb hält push-inputden gesamten Eingabepuffer an, während push-linenur die aktuelle Zeile angehalten wird. Wenn ich einen mehrzeiligen Befehl eingebe, möchte ich den gesamten Befehl aussetzen push-input. Ich finde push-inputes häufiger nützlich als push-line(wenn ich eine Zeile in einem mehrzeiligen Eingabepuffer verzögern möchte, kann ich einfach zum Zeilenanfang navigieren und eine neue Zeile einfügen), also frage ich mich tatsächlich, warum push-linedie Standard-Tastenkombination verwendet wurde und nicht push-input.
Gilles
13

Geben Sie in bash einfach Alt+ ein #.

Wenn Sie fertig sind, drücken Sie Updann Alt+ #.

Das erste setzt ein #am Zeilenanfang, um daraus einen Kommentar zu machen, und akzeptiert dann die Zeile, als hätten Sie gedrückt Enter.

Wenn Sie es dann ein zweites Mal tun, sieht es, dass die Linie bereits ein #am Anfang hat, so dass es sie entfernt und akzeptiert und Ihnen den EnterSchlüssel wieder speichert .

Wenn das zweite Mal , andere nur einfügt #, dann müssen Sie eingeben Alt+ - Alt+ #statt.

Sie können zsh dazu bringen, dasselbe zu tun, indem Sie setzen

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

in Ihrem ~ / .zshrc.

Wenn Sie vi-Bindungen verwenden, können Sie im #Befehlsmodus sowohl bash als auch zsh eingeben.

Mikel
quelle
2
Funktioniert bei mir nicht, der zweite Befehl zum Entfernen der # fügt einfach mehr # an der Vorderseite hinzu.
Lauritz V. Thaulow
1
Funktioniert der erste? Welche Version von Bash verwenden Sie?
Mikel
3
Alt + # funktioniert so, wie Sie es in Ihrem dritten Absatz beschrieben haben, aber nicht wie in Ihrem vierten Absatz, sondern stellt einfach ein weiteres # voran und akzeptiert die Zeile. Ich benutze bash 4.1.5 (1) -release auf Ubuntu 10.10.
Lauritz V. Thaulow
1
Die Sanitäter in bash es ein numerisches Argument erfordert, zum Beispiel Esc+1dann Alt+ #zu wechseln.
Mikel
Das funktioniert, ist aber um einiges umständlicher als nur Strg + A Entf Strg + E, insbesondere bei meinem Tastaturlayout, bei dem Alt + # tatsächlich Alt + Umschalt + 3 ist.
Lauritz V. Thaulow
10

Eines meiner Lieblingsfeatures zshist die integrierte Push-Line-Funktion, die dies erledigt, ohne dass die anderen Antworten hacken. Ich habe es gebunden an Ctrl+ lin meiner .zshrcDatei wie folgt:

bindkey '^L' push-line

Wenn ich dann einen Befehl eingebe und ganz schnell etwas anderes tun muss, kann ich das mit einer Taste aufrufen und eine leere Eingabeaufforderung erhalten. Nachdem Sie den anderen Befehl ausgeführt haben, wird die Eingabeaufforderung automatisch mit dem ausgefüllt, was ich zuvor eingegeben habe.

Sie können sogar mehrere Ebenen davon verketten, und die Befehle werden in umgekehrter Reihenfolge an Sie zurückgegeben, in der Sie sie in die Warteschlange gestellt haben.

Caleb
quelle
5
Gebunden an Ctrl+Qund ESC qstandardmäßig (im Emacs-Modus).
Gilles
Gibt es etwas Ähnliches für Bash?
Magnus
@ Magnus: Bitte überprüfen Sie den Rest der Antworten auf diese Frage. Es gibt Lösungen für bash, nur nicht so elegant.
Caleb
@Caleb, ich hätte es genauer sagen sollen, gibt es eine ähnliche Tastenkombination für Bash?
Magnus
1
Dies ist eindeutig die "richtige" Antwort, für Zsh jedenfalls! Ich möchte nur das push-line-or-editWidget erwähnen , das standardmäßig nicht an eine Keymap gebunden ist. Bei der Eingabeaufforderung der obersten Ebene wird das Gleiche getan wie push-linebei der Eingabeaufforderung der unteren Ebene wird jedoch der gesamte eingegebene Befehl in einen mehrzeiligen Puffer konvertiert. Zwei großartige Funktionen auf einer Tastenkombination! Ich kann das Binden push-line-or-editstatt des Einfachen empfehlen push-line. Sie verlieren nichts und erhalten nützliche Funktionen.
WJV
5

Neben den ctrl- a ctrl- kTrick, wenn man im Bildschirm ist, nur ctrl- a dlösen dann wieder anbringen mitscreen -r

Sie können auch einfach ein anderes Fenster mit ctrl+ öffnena c

Labyrinth
quelle
8
Wenn Sie auf dem Bildschirm sind, öffnen Sie einfach ein anderes Fenster mit Ctrl+A c.
Gilles
1
@Gilles .. es sei denn, Sie müssen einen Aspekt des Shell-Status verwenden (Variablen, Funktionen, Aliase usw.).
Intuited
4

Eine alternative, aber nicht perfekte Möglichkeit, drücken Sie Ctrl-X Ctrl-E. Dadurch wird Ihr Standardeditor geöffnet, der Ihren halb getippten Befehl enthält. Anschließend können Sie Ihren Befehl in einer Datei speichern oder eine neue Shell in Ihrem Editor öffnen. Wenn Sie die neue Shell verlassen, kehren Sie zum Editor zurück und werden beim Speichern des Inhalts automatisch ausgeführt.

Dies ist nicht perfekt, da Sie nicht zu Ihrer ursprünglichen Shell zurückkehren, sondern die Ausführung des Befehls erzwingen oder ihn vollständig verwerfen. Es gibt jedoch keine vorübergehenden Auswahlen oder Löschpuffer, über die Sie sich Sorgen machen müssen, und es gibt auch einige nette Verbesserungen, z. B. wenn 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
forcefsck
quelle
Sehr schöne Alternative. Ich bin Vi-Emacs-Agnostiker, also werde ich mich freuen, wenn ich das als Muschel benutze, wenn Powertools wirklich gebraucht werden. (Apropos vi, ich habe vor einiger Zeit den N64-Linux-Emulator Mupen64Plus ausprobiert. Esc beendet den Emulator, ohne zu speichern. Ich habe bald
Lauritz V. Thaulow
1
@lazyr, für debian / ubuntu starte sudo update-alternatives --config editorund wähle deinen Lieblingseditor. Für andere Systeme stellen Sie die Umgebungsvariablen EDITOR oder VISUAL auf Ihren bevorzugten Editor ein, z. B. fügen Sie export EDITOR=/usr/bin/nanoIhre .bashrc hinzu.
Forcefsck
3

Ähnlich wie beim Hinzufügen #am Zeilenanfang gibt es eine wohl einfachere Methode, bei der ich nicht zum Zeilenanfang zurückkehren muss:

Fügen Sie einfach ein offenes Zitat hinzu und schließen Sie es nicht, egal ob einzeln oder doppelt.

Dann drücken Sie Enter.

Dann drücken Sie CtrlC.

Der Teilbefehl wird in der Befehlshistorie gespeichert (verfügbar über den Aufwärtspfeil), jedoch nicht ausgeführt.

Platzhalter
quelle
2

Wenn Sie zsh eingeben <ESC> q(Escape, dann Q), wird Ihre Eingabeaufforderungszeile abgeschnitten, sodass Sie einen anderen Befehl eingeben können. Sie erhalten Ihren ausgeschnittenen Text bei der nächsten Aufforderung automatisch zurück.

Es kann sich an mehrere Leitungen gleichzeitig erinnern, sodass Sie es verwenden können, während eine Leitung auf Sie wartet. Sie können es sogar für Leerzeilen verwenden, um die Fortsetzung Ihrer Schnittlinie zu verzögern.

Dies ist nicht die effizienteste Methode, wenn Sie mehrere Befehle für die Prüfung / Vorbereitung verwenden müssen (Sie müssen <ESC> qvor jedem Befehl einen neuen eingeben ). Aber ich denke, dass es möglich ist, es an eine kürzere Verknüpfung zu binden.


Wenn Sie nur das Handbuch überprüfen möchten, geben Sie <ESC> h(Escape, dann H) ein. Das führt das run-helpeingebaute aus, mit dem ersten Wort der Befehlszeile als Argument. Sobald Sie fertig sind, finden Sie Ihre Leitung wieder.

loxaxs
quelle
Die meisten Terminals lassen Sie M-qstatt<ESC> q
sleblanc