Wie bearbeite ich den aktuellen Shell-Befehl, ohne ihn auszuführen?

13

Es scheint eine Menge Informationen darüber zu geben, wie Sie einen Befehl mit Ihrem Editor mithilfe des Befehls "Bearbeiten und Ausführen (Cx Ce)" bearbeiten und ausführen können. Ich möchte jedoch den aktuellen Shell-Befehl anwenden Bestimmte Filterung (mithilfe eines Skripts) und Rückgabe an die Eingabeaufforderung zur weiteren Genehmigung / manuellen Änderungen vor der Ausführung. Ist das mit Bash möglich?

Piotr Mazurek
quelle
Dies ist nicht die richtige Antwort auf die Frage, aber versuchen Sie, das ZSH- Terminal anstelle des nativen Bash zu verwenden. Es wird automatisch vervollständigt, führen Sie also keine Befehle sofort aus. Ich habe dieses spezielle Szenario persönlich ausprobiert und muss immer die Eingabetaste drücken, wenn ich eine mache edit-and-execute-command.
Praveen Premaratne
1
Die Verknüpfung, die für mich funktioniert, ist Escape+ V, aber der Befehl wird trotzdem ausgeführt. Um die Problemumgehung zu umgehen, würde ich echovorne hinzufügen , um sie auszuführen, indem ich den Befehl zur Überprüfung auf die Konsole drucke.
Kenorb
2
Können Sie bitte ein konkretes Beispiel geben? Ich verstehe nicht, "bestimmte Filter (mithilfe eines Skripts) anwenden und dann an die Eingabeaufforderung zurückgeben".
Kent
3
@PraveenPremaratne: zsh ist kein Terminal , sondern eine Shell .
Arkadiusz Drabczyk

Antworten:

7

Letztes Update meiner Erfahrung

Der Teil 0"+y$ddin der folgenden Zuordnung ist wirklich etwas, über das Sie sorgfältig nachdenken und ihn an Ihren Geschmack / Workflow / Ihre Erfahrung anpassen sollten.

Zum Beispiel habe ich sehr häufig mehrere Zeilen im Puffer gefunden, in denen ich nur die ausführen möchte, auf der sich der Cursor befindet. in diesem Fall kann ich 0"+y$dd:%d<CR>anstelle von verwenden 0"+y$dd.

Und dies ist nur eines der möglichen Szenarien.

Endgültige Antwort für diejenigen, die mögen vim

Ursprüngliche Antwort

Ich muss oft das Gleiche tun, und ich mache es wie folgt. (Normalerweise verwende ich das set -o viIn bash, daher unterscheiden sich die Punkte 1 und 2 im Folgenden, wenn Sie set -o emacsdie Standardeinstellung verwenden. Basierend auf Ihrer Frage sieht es so aus, als ob die Punkte 1 und 2 in Ctrl+ vereint sind, xgefolgt von Ctrl+ e, was imho schwieriger zu tippen ist .)

  1. drücken Escape, um im normalen Modus zu sein,
  2. Drücken Sie v, um den Editor zum Bearbeiten des Befehls aufzurufen.
  3. Bearbeiten Sie den Befehl nach Belieben.

(Hier stellen Sie die Frage.)

  1. getroffen Escape0"+y$dd:wq,
    • Hinweis: 0"+y$Nicht einfach "+yy, da letztere auch die neue Zeile kopieren würde und dies dazu führen würde, dass der Befehl ausgeführt wird, wenn er in die Befehlszeile eingefügt wird.
  2. Fügen Sie die Zwischenablage in die Befehlszeile ein
    • Wie das geht, hängt wohl von dem Terminal ab, das Sie verwenden. Ich drücke Ctrl+ Alt+ vin URxvt.
  3. Fahren Sie mit der Genehmigung / manuellen Bearbeitung fort.

Dies ist eindeutig nur eine Problemumgehung, die darin besteht, den bearbeiteten Befehl in die Zwischenablage zu kopieren, bevor der gesamte Befehl gelöscht wird, sodass beim Beenden des Editors nichts ausgeführt wird. Es ist jedoch das Beste, was ich für mich selbst bekommen kann.

Aktualisieren

Da mein EDITOR(und VISUAL) gleich ist vim, bearbeite ich den Befehl beim Bearbeiten in vim.

In dieser Hinsicht habe ich festgestellt, dass der Puffer benannt ist /tmp/bash-fc.random, wobei randomes sich um eine 6-stellige alphanumerische Zufallszeichenfolge handelt.

Dies bietet Platz für viele Möglichkeiten, wenn Sie vimals Editor verwenden, da Sie in Ihrem System eine Zuordnung definieren können .vimrc, um die gesamte Sequenz auszuführen Escape0"+y$dd:wq. Ein Befehl, den Sie beim Bearbeiten einer Befehlszeile selten verwenden würden, ist beispielsweise Leaderd: Daher können Sie den folgenden mapPing in Ihre .vimrcDatei einfügen

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

so dass Schritt 4 im obigen Rezept wird

  1. schlagen EscapeLeaderd
Enrico Maria De Angelis
quelle
Für mich ist dies der beste Weg, um Befehle zu bearbeiten
A.Villegas
2

Dies ist in Bash / readline nicht möglich, in zsh jedoch mit dem folgenden edit-command-lineBefehl:

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

Drücken Sie nun Control- x Control- e, um Ihren Editor zu öffnen, die Zeile zu bearbeiten und den Editor zu verlassen. Sie sehen die aktualisierte Befehlszeile, die jedoch nicht automatisch ausgeführt wird.

Arkadiusz Drabczyk
quelle
1

Jetzt, wo ich darüber nachdenke, ist vielleicht eine Variation dessen, was @kenorb in einem Kommentar vorgeschlagen hat, die beste Problemumgehung (da es anscheinend keine Lösung gibt), wenn wir uns daran halten wollen bash.

Sie können dem Befehl ein #(das Kommentarzeichen in bash) voranstellen , anstatt echo. Wenn Sie dann den Exitor verlassen, ist der Befehl unwirksam und Sie müssen nur die Taste drücken arrow up(oder k, falls Sie sie verwenden set -o vi), entfernen# und bestätigen.

Beachten Sie, dass diese Strategie nur wenige Tastenanschläge hinzufügt, sodass sie je nach Eingabeebene ziemlich effizient sein kann.

Enrico Maria De Angelis
quelle
1

Diese Stücke könnten Sie näher bringen:

a) Ersetzen Sie die normale Bindung für Newline Newline (Strg-M). bind -x '"\C-M":date"

b) Nehmen Sie die aktuelle Zeile aus dem Verlauf mit !#

Ersetzen Sie das Datum durch ein beliebiges Skript.

c) manuell bearbeiten

d) wenn nötig, irgendwie einbinden !!:p den neuen Befehl die Befehlszeile ein, führen Sie ihn jedoch nicht aus, sodass Sie ihn manuell bearbeiten können.

e) Verwenden von Strg-J Senden des bearbeiteten Befehls anstelle eines Zeilenumbruchs

oder sie könnten nicht ....

ShpielMeister
quelle
1

In bash gibt es eine Option, um Befehle aus dem Verlauf zu ändern, ohne sie auszuführen. Ich bin nicht sicher, ob es möglich ist, ein Skript dafür zu verwenden, scheint nicht wahrscheinlich zu sein. Sie können jedoch Änderungen mithilfe von Verlaufsmodifikatoren vornehmen.

  1. Aktivieren Sie die Option histverify, um die Ausführung des geänderten Befehls zu verhindern
  2. Verwenden Sie die Modifikatorkette, um den letzten Befehl zu ändern
  3. Verwenden "!!" um Ihr Ergebnis zur endgültigen Bearbeitung in die Befehlszeile zu setzen

So sieht es aus:

$ 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
quelle
1

Ich möchte Sie auf das Composure- Framework für Bash verweisen (ich bin nicht damit verbunden): https://github.com/erichs/composure

Es bietet draftund reviseFunktionen die klingen wie sie mit helfen könnte , was Sie versuchen zu tun. Hier ist ein (langes) Zitat aus der Readme-Datei des Projekts:

Composure hilft, indem Sie schnell einfache Shell-Funktionen entwerfen und Ihre langen Rohrfilter und komplexen Befehle in lesbare und wiederverwendbare Blöcke aufteilen können.

Entwurf zuerst, später Fragen stellen

Wenn Sie Ihren Edelstein eines Befehls hergestellt haben, werfen Sie ihn nicht weg! Verwenden Sie draft ()und geben Sie ihm einen guten Namen. Dadurch wird Ihr letzter Befehl als Funktion gespeichert, die Sie später wiederverwenden können. Betrachten Sie es als einen groben Entwurf.

  $ 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

Überarbeiten, überarbeiten, überarbeiten!

Nachdem Sie eine minimale Shell-Funktion haben, möchten Sie diese möglicherweise durch Refactoring und Überarbeitung verbessern. Verwenden Sie den revise ()Befehl, um Ihre Shell-Funktion in Ihrem bevorzugten Editor zu überarbeiten.

  • verallgemeinern Sie Funktionen mit Eingabeparametern
  • Funktionen hinzufügen oder entfernen
  • Fügen Sie unterstützende Metadaten zur Dokumentation hinzu

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

Zumindest mit einer Tastenkombination scheint dies nicht möglich zu sein:

$ 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
quelle