Wie kann ich den Bash-Verlauf durchsuchen und einen Befehl erneut ausführen?

297

Kann ich den Verlauf in bash durchsuchen und das Ergebnis ausführen?

Richard Hoskins
quelle

Antworten:

428

Geben Sie Ctrl Rin die Befehlszeile ein und beginnen Sie mit der Eingabe des vorherigen Befehls. Sobald ein Ergebnis angezeigt wird, drücken Sie die Taste Ctrl R, um weitere Übereinstimmungen anzuzeigen. Wenn der gewünschte Befehl angezeigt wird, drücken Sie einfachEnter

Beachten Sie, dass while Ctrl Rdie Standardeinstellung ist, wenn Sie möchten, dass der Befehl ( reverse-search-history) an Ctrl TFolgendes gebunden wird :

Bind '"\ Ct": Reverse-Search-History'

Es gibt eine ganze Reihe weiterer readline-bindbarer Befehle, die Ihnen ebenfalls zur Verfügung stehen. Schauen Sie sich die bashManpage an .

Bash verfügt über zahlreiche Funktionen zum Suchen und Zugreifen auf den interaktiven Befehlsverlauf. Das grundlegendste davon ist das historyeingebaute. Tippen Sie einfach:

$ history

Gibt eine Liste von Befehlen zusammen mit einem numerischen Index aus, wie zum Beispiel:

$ history
1 klar
2 ls-al
3 vim ~ / somefile.txt
4 geschichte
$

Sie können dann jeden dieser Befehle unter Verwendung des numerischen Index ausführen, indem Sie dem Index eine einzelne voranstellen !, wie Mitch ausführte:

$! 1

Führt den clearBefehl aus. Die Geschichte builtin hat viele Funktionen selbst, Sie mehr in der sehen bashund historyman - Seiten.

Sie können auch relative negative Offsets angeben, wenn Sie den !Bezeichner verwenden. Wenn wir also unsere Verlaufsliste oben vimerneut ausführen möchten, können wir Folgendes tun:

$! -2

Das bedeutet, dass bash den Befehl ausführen soll, den Sie vor "zwei Befehlen" ausgeführt haben. Um den vorherigen Befehl in der Verlaufsliste auszuführen, können wir einfach verwenden !!(was nur eine Abkürzung für ist !-1).

Der !Bezeichner beschränkt sich nicht auf die numerische Angabe des auszuführenden Befehls. hayalci hat gezeigt, dass Sie anweisen können bash, einen Befehl basierend auf dem Text auszuführen, mit dem er beginnt (using !), oder basierend auf dem Text im Befehl selbst (using !?). Unter Verwendung der obigen Beispielverlaufsliste müssen wir nur Folgendes eingeben, wenn wir clearerneut ausführen möchten:

$! cl

und drücken Sie Enter. Und was ist mit vim? Das ist so einfach wie:

$!? einige

Der wichtigste Punkt in Hayalcis Antwort ist der Aufruf an das shopteingebaute System:

$ shopt -s histverifizieren

Auf diese Weise wird die Verlaufsüberprüfung aktiviert, sodass Befehle, die mit dem,, und den Bezeichnern übereinstimmen !, nicht blind ausgeführt, sondern in der Befehlszeile eingegeben werden, damit Sie sicherstellen können, dass sie vor der Ausführung nichts Böses tun. Dies ist umso wichtiger, wenn Sie als Root-Benutzer Befehle ausführen. Diese Option kann in Ihrer Startdatei festgelegt werden, sodass sie bei jeder Anmeldung festgelegt wird.!!!?.bashrc

Wie bereits erwähnt, können alle diese Informationen aus der bashManpage entnommen werden . Für die!, !! und!? Bezeichner finden Sie in Abschnitt 9.3, Verlaufserweiterung .

Gemeinschaft
quelle
39
+1 Ich benutze Linux seit über 12 Jahren für alle Systeme. Ich wusste nicht, dass es das gibt. Ich wünschte, ich könnte +10, wie habe ich es vermisst?
Aiden Bell
1
Bei vielen Systemen wird das gleiche durch Drücken des Aufwärtspfeils erreicht.
mas
Wenn jemand '!', '!!', '!?', 'History | grep 'und' ctrl-r 'in eine umfassende Antwort, ich würde es auswählen
Richard Hoskins
shoptGeht in bashrc, nicht in bash_profile (oder wird nicht für Shells aktiviert, die keine Login-Shells sind).
Tobu
2
Auch nach Drücken von STRG + R können Sie STRG + UMSCHALT + R mehrmals verwenden, um zum vorherigen Befehl zurückzukehren
Gal Bracha
37

Alternativ dazu crtl+Rkönnen Sie den Verlauf durchsuchen, indem Sie Folgendes eingeben

!text

Dadurch wird der Verlauf nach dem neuesten Befehl durchsucht, der mit 'text' beginnt .

Aber ich schlage vor, Sie fügen dies in Ihre .bashrc-Datei ein, um die Ausführung eines falschen Befehls zu verhindern.

shopt -s histverify

Dies weist bash , so dass nach irgendwelchen Geschichte Aktionen (wie !!:s/prev_text/after_text), ist es die resultierende Zeile der Eingabeaufforderung stellt. Anschließend können Sie den Befehl überprüfen oder bearbeiten und anschließend die Eingabetaste drücken.

hayalci
quelle
5
Verwenden Sie!? Text, um den letzten Befehl erneut auszuführen, der (im Gegensatz zum Beginnen mit) "text" enthält.
mark4o
3
Wenn jemand '!', '!!', '!?', 'History | grep 'und' ctrl-r 'in eine umfassende Antwort, würde ich es auswählen.
Richard Hoskins
32

Sie könnten auch tun:

history | grep "stuff"

es würde so etwas wie zurückgeben

num stuff

dann kannst du tippen

!num
Mitch
quelle
15

Ich bevorzuge es, History-Search-Backward gegenüber Reverse-Search-History zu verwenden. Ersteres lässt Sie ein paar Zeichen des Befehls eingeben und dann die Suchtaste drücken, anstatt zuerst die Suchtaste zu drücken und dann die Suchzeichenfolge einzugeben.

Standardmäßig binden Mp und Mn auf meinem System an ähnliche Funktionen, aber ich bevorzuge das Binden der Pfeiltasten:

bind '"\e[A":history-search-backward'
bind '"\e[B":history-search-forward'
Keith
quelle
13

Ich habe einen wirklich tollen Alias, h. Es ist wirklich nur "history | grep", aber ich filtere vorherige "h command" -Einträge mit "grep -E -v" aus

alias h="history | grep -E -v '^ *[0-9]+ *h ' | grep "

gebraucht wie

h aliases
2003  less .bash_aliases
CurtH
quelle
1
Dies kann auch durch Hinzufügen des Befehls zu erfolgen HISTIGNORE.
Tanenbring
12

Hervorragender Bericht, Sean! Ich würde das in einen Kommentar schreiben, aber ich bin ein paar Rufpunkte schüchtern. :-)

Eine andere verwandte und nützliche Technik ist die Fähigkeit, einen vorherigen Befehl auszuführen, während ein Wort geändert wird. Angenommen, Sie haben den Verzeichnisnamen eingegeben oder möchten den Dateinamen ändern:

Ich heiße Bob
mein Name ist Bob
$ ^ Bob ^ Jordan
Echo, mein Name ist Jordan
Mein Name ist Jordan

Beachten Sie, dass der Befehl erweitert, ersetzt und ausgegeben wird, bevor der Befehl ausgeführt wird. Wenn also der falsche Befehl ausgeführt wird, können Sie sehen, was Bash gedacht hat.

Jordan
quelle
6

Da die Navigation durch den Verlauf mit Strg-R IMO umständlich ist, sollten Sie Folgendes berücksichtigen :

https://github.com/dvorka/hstr

Dies macht die Navigation viel einfacher, einfacher und effizienter - einschließlich der Ausführung des Befehls:

Bildbeschreibung hier eingeben

Martin Dvorak
quelle
Wie benutzt man es? Welche Tasten müssen gedrückt werden, um dieses Bild zu sehen?
Nakilon,
2
Sobald Sie hh installiert haben, können Sie entweder den Befehl hh verwenden ODER ihn an eine beliebige Tastenkombination (normalerweise Strg-R) binden, wie in der Dokumentation beschrieben.
Martin Dvorak
es bindet sich ctrl + rjetzt standardmäßig an
Alleo
4

Geben Sie an der Bash-Eingabeaufforderung control-R ein und geben Sie dann einige Zeichen des gewünschten Befehls ein. Die Readline-Funktion von Bash durchsucht den Befehlsverlauf nach diesem Befehl.

Nachdem Sie die Suche gestartet haben, können Sie erneut control-R eingeben, um zum nächsten passenden Befehl zu springen.

John1024
quelle
3

Wenn Sie Ihre Shell konfigurieren verwenden viTastenbelegungen ( set -o vioder mit set editing-mode viin $HOME/.inputrc), dann suchen Sie mit <Esc>/some-command<Return>und schlagen n(nächste) oder Shift-n(zurück) , um durch die Geschichte Kommandozeile.

Fernando Basso
quelle
Dieser ist den vim-Benutzern am nächsten.
Gabor Marton
2

CTRL+ Rfunktioniert einwandfrei, wie von @ John1024 vorgeschlagen, ist aber etwas mühsam, wenn viele Ihrer letzten Befehle ähnlich sind und Sie einen schnellen Weg suchen möchten, um alle zu scannen. Eine Alternative wäre zu verwenden history:

$ history | grep keyword
Mureinik
quelle
0

Ich mag HSTR, aber ich kann es manchmal nicht installieren. Also habe ich einen Alias ​​mit fzf geschrieben, der sein Verhalten nachahmt ( hxfür "history execute ")

alias hx='eval $(history | sed "s/^ *[0-9]* *//g" | fzf --tac --tiebreak=index --height=10)'
  • history : Nun, holen Sie sich die Geschichte
  • sed : Entferne die Nummernspalte aus der Liste (POSIX)
  • fzf: Hier ist die Magie: Ermöglicht die interaktive Fuzzy-Suche in der Liste oder das Bewegen mit C-Jund C-KAusführen eines Befehls mit Enter.
  • --height : Stellen Sie die Anzahl der angezeigten Zeilen ein.
  • --tac : Liste zurücksetzen (logischer für eine Geschichte)
  • --tiebreak=index : Behalte die Verlaufsreihenfolge, wenn FZF die Ergebnisse aktualisiert
Biggybi
quelle