Wie binde ich in bash eine Funktionstaste an einen Befehl?

91

Beispiel: Ich möchte den F12Schlüssel so an den Befehl binden, echo "foobar"dass jedes Mal, wenn ich F12die Meldung "foobar" drücke, auf dem Bildschirm gedruckt wird. Im Idealfall kann es sich um einen beliebigen Shell-Befehl handeln, nicht nur um eingebaute Befehle. Wie geht man damit um?

SiegeX
quelle

Antworten:

162

Sie können die von einer Taste ausgegebene Zeichenfolge bestimmen, indem Sie Ctrl- vin der Befehlszeile drücken und dann die Taste drücken, an der Sie interessiert sind. Auf meinem System für F12bekomme ich ^[[24~. Das ^[repräsentiert Esc. Verschiedene Arten von Terminals oder Terminalemulatoren können unterschiedliche Codes für denselben Schlüssel ausgeben.

An einer Bash-Eingabeaufforderung können Sie einen Befehl wie diesen eingeben, um das Schlüsselmakro zu aktivieren und es auszuprobieren.

bind '"\e[24~":"foobar"'

Wenn Sie jetzt drücken F12, wird in der Befehlszeile "foobar" zur weiteren Bearbeitung angezeigt. Wenn Sie möchten, dass ein Tastendruck sofort einen Befehl eingibt, können Sie eine neue Zeile hinzufügen:

bind '"\e[24~":"pwd\n"'

Wenn Sie jetzt drücken F12, wird das aktuelle Verzeichnis angezeigt, ohne drücken zu müssen Enter. Was ist, wenn Sie bereits etwas in die Zeile eingegeben haben und dieses verwenden, das automatisch ausgeführt wird? Es könnte chaotisch werden. Sie können die Zeile jedoch als Teil Ihres Makros löschen:

bind '"\e[24~":"\C-k \C-upwd\n"'

Das Leerzeichen stellt sicher, dass das Ctrl- uetwas zu löschen hat, damit die Glocke nicht läutet.

Sobald das Makro wie gewünscht funktioniert, können Sie es dauerhaft machen, indem Sie es Ihrer ~/.inputrcDatei hinzufügen . Der bindBefehl oder die äußeren einfachen Anführungszeichen sind nicht erforderlich :

"\e[24~":"\C-k \C-upwd\n"

Bearbeiten:

Sie können auch eine Schlüsselbindung erstellen, die etwas ausführt, ohne die aktuelle Befehlszeile zu stören.

bind -x '"\eW":"who"'

Während Sie dann einen Befehl eingeben, für den beispielsweise ein Benutzername erforderlich ist, und die Namen der angemeldeten Benutzer kennen müssen, können Sie Alt- Shift- drücken. WDie Ausgabe von whowird angezeigt und die Eingabeaufforderung wird erneut ausgegeben mit intaktem Teilbefehl und dem Cursor an der gleichen Position in der Zeile.

Leider funktioniert dies nicht richtig für Tasten, F12die mehr als zwei Zeichen ausgeben. In einigen Fällen kann dies umgangen werden.

Der Befehl ( whoin diesem Fall) kann eine beliebige ausführbare Datei sein - ein Programm, ein Skript oder eine Funktion.

Bis auf weiteres angehalten.
quelle
2
Was ist, wenn ich eine Bindung zu "Strg + Q" hinzufügen möchte?
Kubudi
5
@kubudi: bind '"\C-q": menu-complete'zum Beispiel (oder in Ihrem ~/.inputrc: "\C-q": menu-complete). Möglicherweise müssen stty -ixonSie ~/.bashrcauch die Flusskontrolle deaktivieren und ^ S und ^ Q verfügbar machen.
Bis auf weiteres angehalten.
Sie sagen, das ^[repräsentiert escund dann scheinen Sie es \ein Ihrem Beispiel zu ersetzen . Können Sie bitte erklären, warum?
Entferner
1
@ Remover: Dies ^[ist die Ausgabedarstellung. Dies \eist eine Möglichkeit, es einzugeben ( ^[funktioniert dafür nicht).
Bis auf weiteres angehalten.
Wie kann ich "\ Cz" binden? Ich würde gerne so etwas wie das bekommen, was für zsh auf mereun.net/2014/03/21/how-to-boost-your-vim-productivity
pkoch
19

Sie können Bash-Schlüsselbindungen in ~/.inputrc(Konfigurationsdatei für die GNU Readline-Bibliothek) definieren. Die Syntax lautet

<Keysym oder Schlüsselname>: Makro

beispielsweise:

Control-o: "> output"

erstellt ein Makro, das beim Drücken "> output" einfügt ControlO

 "\e[11~": "echo foobar"

erstellt ein Makro, das beim Drücken "echo foobar" einfügt F1... Ich weiß nicht, wofür das Keysym nicht verfügbar F11ist.

Bearbeiten:

.inputrcversteht die \nEscape-Sequenz für Linefeed, so dass Sie verwenden können

 "\e[11~": "echo foobar\n"

Dies drückt effektiv die Eingabetaste, nachdem der Befehl ausgegeben wurde.

Barton Chittenden
quelle
4
Sie können "\ n" in einem Makro verwenden, um ein Zeilenumbruchzeichen hinzuzufügen:
Barton Chittenden
Dies funktioniert für mich besser, da es die Schlüsselzuordnung beim Öffnen eines Terminals definiert.
Heldraug
Für die AltVerwendung \e, zum Beispiel "\eo": "> output".
Jānis Elmeris
Ein ausführlicheres Tutorial zur Verwendung finden .inputrcSie unter hackaday.com/2018/01/19/linux-fu-custom-bash-command-completion
Josh Habdas
1
@ArthurHenriqueDellaFraga Ich habe die Antwort bearbeitet. Es wird in Ihrem Home-Verzeichnis sein. Wenn es nicht existiert, können Sie es erstellen.
Barton Chittenden
7

Diese Lösung ist spezifisch für X11-Umgebungen und hat nichts mit Bash zu tun, sondern fügt Ihren .Xmodmaps Folgendes hinzu

 % loadkeys
 keycode 88 = F12
 string F12 = "foobar"
 %

sendet die Zeichenfolge "foobar" an das Terminal, wenn F12 gedrückt wird.

Wesley Rice
quelle
Beachten Sie, dass dies nicht mit der Shell identisch ist, die einen Befehl ausführt. Wenn Sie tatsächlich einen Befehl ausführen möchten, müssen Sie die Eingabetaste drücken (oder die gesendete Zeichenfolge erledigt dies für Sie). Wahrscheinlich wollen Sie auch sicher sein und zuerst die Linie frei machen.
Cascabel
2
Das wäre großartig, aber ab Fedora 20 scheint es sowieso nicht zu funktionieren. Ich habe sogar versucht, mit xev zuerst den richtigen Schlüsselcode für F12 zu finden (in meinem Fall 96) und ihn anstelle von 88 zu verwenden. Keiner von beiden funktioniert.
BobDoolittle
2

Ich wollte mich Ctrl+Ban einen Befehl binden . Inspiriert von einer Antwort oben, versuchte ich zu verwenden bind, konnte aber nicht herausfinden, in welche Reihe von kryptischen Schnörkeln ( \e[24~?) Übersetzt werden Ctrl+B.

Gehen Sie auf einem Mac zu Einstellungen der Terminal-App, Profile -> Tastatur -> +und drücken Sie die Tastenkombination, nach der Sie suchen. Für mich Ctrl+Bergab sich, \002dass ich erfolgreich an Befehl gebunden habe

bind '"\002":"echo command"'

Wenn Sie möchten, dass der Befehl sofort ausgeführt wird (und nicht nur in die Eingabeaufforderung eingefügt wird), können Sie die Eingabetaste am Ende Ihres Befehls wie folgt hinzufügen:

bind '"\002":"echo command\015"'

Peter Perháč
quelle