Grundlegendes zum Ausrufezeichen (!) In bash

108

ich benutzte

history | less

Um die Zeilen der vorherigen Befehle zu erhalten und aus den Zahlen auf der linken Seite, fand ich die Zeile, die ich wiederholen wollte (zB 22) und tat es

!22

an der Eingabeaufforderung und es funktionierte - Ausführen der Reihe von Befehlen in der Zeile, die ich zu dieser Zeit tat. Ich kann nicht herausfinden, wo das Ausrufezeichen verwendet wird, was es in Bezug auf die von bash durchgeführten Aktionen darstellt und wo es verwendet werden soll. Aus der Dokumentation sehe ich keine Erklärung, die "greifbar" ist.

Vass
quelle
6
Diese Antwort könnte helfen
Michael Mrozek
9
Keine Antwort auf Ihre Frage, aber mit <Strg> + R können Sie Ihren Verlauf interaktiv durchsuchen und sofort ausführen, wenn Sie das Gesuchte gefunden haben.
Kasterma

Antworten:

144

!ist eine Funktion, die ursprünglich in der C-Shell vorkam , bevor man sich auf Terminals mit Pfeiltasten verlassen konnte. Es ist besonders nützlich, wenn Sie die aktuelle Befehlsnummer zur Eingabeaufforderung ( PS1="\!$ ") hinzufügen, damit Sie schnell auf Ihren Bildschirm schauen können, um Nummern für frühere Befehle abzurufen.

Jetzt, da Sie Pfeiltasten verwenden können und Dinge wie Ctrl-Rdas Durchsuchen des Befehlsverlaufs, sehe ich keine große Verwendung für die Funktion.

Eine Variante, die Sie vielleicht immer noch nützlich finden, ist die !!, bei der der vorherige Befehl erneut ausgeführt wird. Auf seinem eigenen, finde ich nicht !!Enterschneller als gerade Enter, aber es kann hilfreich sein , wenn sie in einen größeren Befehl kombiniert.

Beispiel: Ein häufiger Pilotfehler auf sudobasierten Systemen besteht darin, das sudoPräfix eines Befehls zu vergessen, für den zusätzliche Berechtigungen erforderlich sind. Ein Anfänger gibt den gesamten Befehl erneut ein. Der fleißige Schüler bearbeitet den Befehl aus dem Befehlsverlauf der Shell. Der Erleuchtete tippt sudo !!.

Mit Bash können Sie die !Verarbeitung in der Shell mit set +o histexpandoder deaktivieren set +H. Du kannst es in Zsh mit deaktivieren set -K.

Warren Young
quelle
4
Ich finde Strg-P ​​Strg-J ziemlich schnell; Zumindest schneller als Up Enter.
Ephemient
24
Wenn Sie nur den letzten Befehl ausführen möchten, ist Up / Enter in Ordnung, aber wenn Sie ihn auf irgendeine Weise ergänzen möchten (sagen wir, Sie haben es vergessen sudooder so), können Sie dies sudo !!zum Beispiel tun . Das ist vielleicht etwas schneller als "Nach oben / Strg-A (oder nach Hause, wenn Sie Glück haben) / sudo / space / enter". YMMV. :)
1
@ AquariusPower: Zitieren Sie es einfach. Entweder echo 'Hi!'oder echo "Hi!"oder echo Hi\!. Alle machen das Gleiche.
Warren Young
1
setopt NO_BANG_HISTin zsh könnte einprägsamer sein als -K.
Gregory
48

Wenn es hier keine längere Antwort gibt, gibt es auf jeden Fall eine für Super User, da ich vor kurzem eine gelesen habe. In der Bash-Manpage finden Sie einen riesigen Abschnitt mit dem Titel HISTORY EXPANSION zu diesem Thema.

Sie können einen ganzen Host mehr als nur den letzten Befehl oder Befehl Nummer X !catausführen. Sie können Dinge tun, wie den letzten Befehl auszuführen, mit dem begonnen wurde cat. Oder !?bash?:s/bash/csh/führt den letzten Befehl aus, der enthält, ihn bashaber durch ersetzt csh.

Schrei Havok
quelle
3
Obwohl dies keine direkte Antwort auf die Frage von OP ist, sind deutlich mehr positive Stimmen erforderlich. So nützlich! Danke, Havok.
Malvim
Äh, ich sollte wirklich in die Manpage schauen, bevor ich anfange zu googeln.
erikbwork
1
!!:s/bash/csh/führt tatsächlich den letzten Befehl aus und ersetzt bash durch csh, falls vorhanden. Nicht der letzte Befehl, der Bash enthielt. Das wäre !?bash?:s/bash/csh/oder vielleicht!?bash?:s/%/csh/
cde
Nachdem ich Bash mehrere Jahre lang ausgiebig genutzt hatte, stellte ich schockiert fest, dass ich dieses Keyword noch nie zuvor gekannt hatte, und obwohl ich stundenlang durch die manSeiten geblättert habe , ist diese Funktion unglaublich undurchsichtig. Vielen Dank, dass Sie auf den relevanten Abschnitt hingewiesen haben. Dies ist die einzige Stelle in den aktuellen Dokumenten, an der sie ihn ausreichend erläutern.
Steve Benner
39

Es kann noch viel mehr getan werden mit !:

  • Führen Sie einen Befehl aus, der vor 3 Befehlen eingegeben wurde: !-3
  • Führen Sie einen Befehl aus, der mit beginnt !ls

und vieles mehr. Siehe 15 Linux Bash History-Erweiterungsbeispiele, die Sie kennen sollten

user379997
quelle
Upvoted dies. Keine der anderen Antworten hatte einen dieser cleveren Tricks.
Gergely Lukacsy
Upvoted, weil www.thegeekstuff.com einfach eine fantastische Ressource ist, und dies war einer der wenigen Linux-Artikel, die ich zuvor noch nicht gesehen hatte. Sehr hilfreich.
Steve Benner
4

Ein Freund von mir hat mir Folgendes per E-Mail geschickt:

Es ist Teil der GNU History Library. In Bash wird es verwendet, um Befehle in Ihrem Verlauf erneut auszuführen. Wenn Sie Hardcore sein möchten, finden Sie Implementierungsdetails in bash-4.1 / lib / readline / histexpand.c unter history_expansion_char.

Vass
quelle
3

Natürlich können Sie !!den letzten Befehl in der Bash-Shell wiederverwenden. Und dann müssen Sie !$den letzten Teil Ihres letzten Befehls wiederverwenden.

zB eine Datei ansehen

less path/to/your/file.txt

Wenn Sie jetzt dieselbe Datei bearbeiten möchten, können Sie !$nur den Dateipfad des letzten Befehls abrufen

vim !$
Teshan Shanuka J
quelle
1
Ah, ich hatte gehofft, das zu finden. Wie verhält es sich mit zwei Argumenten?
Jonathan
Es wird nur das letzte Argument der beiden wiederverwenden. $touch f1 f2und wird dann $vim !$auswerten$vim f2
Teshan Shanuka J