Wie mache ich Änderungen im Befehlsverlauf rückgängig?

12

In UNIX-Systemen können Sie die oberen und unteren Pfeile drücken, um durch die vorherigen Befehle zu navigieren. Das ist sehr praktisch.

Manchmal gehe ich nach oben und finde einen Befehl, den ich wieder verwenden möchte, aber mit einigen Variationen. Wenn ich solche Änderungen vornehme, kann ich den ursprünglichen Befehl nur zurückerhalten, wenn ich ihn einchecke history.

Gibt es eine Möglichkeit, die Änderungen am Befehl im Verlauf, auf den über Schlüssel zugegriffen wird, rückgängig zu machen?

Meine aktuelle Problemumgehung besteht darin, a voranzustellen # , dem Befehl zu haben. Auf diese Weise wird der aktuelle Befehl als Kommentar ausgeführt, sodass nichts passiert. Dann kann ich mit den Tasten noch einmal durch die Befehle blättern. Das Problem ist, dass der Befehl, den ich verwendet habe, in der Liste möglicherweise sehr weit entfernt ist. Daher ist es ein bisschen, zweihundert Mal wieder nach oben zu gehen. Control + R ist auch keine Lösung, da ich mich möglicherweise nicht genau daran erinnere, wonach ich gesucht habe.

Beispiel

Ich habe Folgendes eingegeben: "Vor 50 Befehlen":

ls -l /etc/httpd/conf/

Jetzt ging ich zu dieser Zeile und änderte sie in

ls -l /etc/init.d/

drückte aber nicht die Eingabetaste. Jetzt möchte ich wieder zum kommen ls -l /etc/httpd/conf/.

Meine Umgebung

$ echo $SHELL
/bin/bash
$ echo $TERM
xterm
fedorqui
quelle
Dass der Befehlsverlauf geändert wird, ist wahrscheinlich eine (falsche) Funktion der von Ihnen verwendeten Shell. In kshkönnen Sie beispielsweise Verlaufseinträge bearbeiten und aufrufen, ohne die "vorherige Version" des Eintrags zu löschen. Sie haben alle aufgerufenen Befehle zur Verfügung.
Janis
Mit "es ändert sich" meine ich Folgendes: Wenn ich bei einem vorherigen Befehl, den ich nach dem Erreichen mit den Pfeilen geändert habe, mit den Pfeilen auf und ab gehe, zeigt der alte Befehl nicht an, wie er war, sondern wie ich ihn geändert habe es. Wenn ich "enter" eingebe, um einen Befehl auszuführen, wird dieser alte Befehl natürlich so sein, wie er ursprünglich war. Aber genau das versuche ich zu vermeiden und suche nach einer Möglichkeit, den Befehl auf seinen Anfangswert zurückzusetzen.
Fedorqui
1
Auch in diesem Fall kshscheint sich das Verhalten hier zu unterscheiden. Die Optionen für die Verlaufsbearbeitung hängen auch vom ausgewählten Bearbeitungsmodus ab. Im kshvi-Modus zum Beispiel wird der alte Eintrag nicht überschrieben, und ich kann auch einen Rückgängig-Befehl wie in vimit 'u' ausgeben .
Janis
Ähm, das klingt sehr vielversprechend. Ich arbeite jetzt in Bash und denke derzeit nicht darüber nach, zu wechseln ksh, aber es ist gut zu wissen, dass es so etwas dort gibt.
Fedorqui
Ich möchte wissen, wo bash den letzten Befehlsverlauf speichert, bevor ich beim Schließen der Shell in die Verlaufsdatei schreibe. Dies kann hilfreich sein, um festzustellen, ob dies möglich ist. Irgendjemand? Ich dachte, es könnte sich um eine der Shell-Variablen handeln, habe aber momentan keine Zeit, das Handbuch zu durchforsten.
Iyrin

Antworten:

10

Solange Sie einen Verlaufseintrag bearbeitet, aber noch nicht gedrückt Enterhaben, drücken Sie wiederholt Ctrl+ _- den undoBefehl - , um zum ursprünglichen Eintrag zurückzukehren, bis keine weiteren Änderungen mehr vorgenommen werden. Sie kehren zum ursprünglichen Eintrag zurück.

Gilles 'SO - hör auf böse zu sein'
quelle
5

Kehren Sie zum ursprünglichen Befehl zurück, wenn Sie mehrere Änderungen an der Zeile vorgenommen haben:

revert-line (M-r) 
    Undo all changes made to this line. This is like 
executing the undo command enough times to get back to the beginning.

Mist der Meta-Schlüssel, der altrfür mich ist.


Kostenlose, aber hilfreiche Informationen

Wenn Sie einen Befehl ausgeführt haben , wie er zuvor von OP ausgeführt wurde (es passiert), müssen Sie nichts rückgängig machen, da die Befehle von der GNU Readline- Bibliothek verarbeitet und gespeichert werden und erst nach$HISTFILE dem Beenden der Shell beschrieben werden. Der Grund, warum ich dies erwähne, ist, dass Sie nicht genau grepdas $HISTFILEerwarten können und es möglicherweise nicht ideal ist, die Shell zu verlassen.

Hier sind einige Optionen, mit denen Sie verhindern können, dass Sie durch alle vorherigen Readline-Befehle zurückblättern.

Wenn Sie sich an einen Teil des Befehls erinnern , drücken Sie ctrl+ rund geben Sie ein, woran Sie sich erinnern, um frühere Befehle zu durchsuchen, die diese Zeichenfolge enthalten. Durch erneutes Drücken von ctrl+ rwird der nächstletzte angezeigt, der rückwärts sucht.

Geben Sie beispielsweise ls -ldann ctrl+ rso oft , wie es den vorherigen Befehl finden nehmen Sie suchen. Wenn Sie daran vorbeirollen, sucht ctrl+ svon der aktuellen Position aus vorwärts.

Der fceingebaute Befehl bash ist hilfreich, um die Indexnummern neben früheren Readline-Befehlen aufzulisten .

fc -l -100 listet die vorherigen 100 Befehle in readline auf.

Wenn OP weiß, dass er nach einem vorherigen ls -lBefehl sucht , kann er die Ausgabe grepwie folgt weiterleiten :fc -l -100 | grep 'ls -l'

Dies sollte eine Liste vorheriger ls -lBefehle ausgeben, denen eine Indexnummer vorangestellt ist. Die Ausgabe sieht folgendermaßen aus:
2065 ls -l

Jetzt können Sie den Ereignisbezeichner verwenden, !nin dem nsich die Indexnummer befindet. In diesem Beispiel wird die Ausführung !2065auf erweitert ls -l.


Obwohl es im Nachhinein nicht hilft, sollte jeder, der beim Ändern früherer Befehle den aktuellen Befehlsverlauf beibehalten möchte, den HISTORY EXPANSIONAbschnitt von lesen man bash. Hier sind einige alternative Methoden zum Ändern alter Befehle, ohne den Verlauf zu überschreiben.

Der Event DesignatorsAbschnitt zeigt, wie Sie Zeichenfolgen mit dem zuletzt verwendeten Befehl einfach bearbeiten können.

^string1^string2^
              Quick  substitution.  Repeat the previous command, replacing string1 with string2.  Equivalent to
              ``!!:s/string1/string2/'' (see Modifiers below).

Beispiel:

$ echo foo
foo 
$ ^foo^bar
echo bar
bar

Die neuesten Befehle zeigen nun:

echo foo
echo bar

Im obigen Beispiel wird auch erläutert, wie sedeine Zeichenfolge in einem Ereignisbezeichner ersetzt wird.

!-n    Refer to the current command minus n.

Wenn also 3 Befehle im Verlauf vorhanden sind echo foo, würden Sie Folgendes verwenden:
!-3:s/foo/bar

Beachten Sie, dass in diesem Fall Ereignisbezeichner in Ihrem Verlauf als ausgeführter Befehl angezeigt werden echo bar. Es wird nicht in der Geschichte als angezeigt !-3:s/foo/bar.

Wirf das einfach raus, da es eng verwandt zu sein scheint, auch wenn es eher ein "Nicht tun" ist als die "Rückgängig" -Lösung, nach der OP sucht.

Iyrin
quelle
Das ist schön, vielen Dank für die detaillierten Informationen. Ich akzeptiere Gilles 'Antwort, da sie genau das tut, wonach ich suche, während Sie hier davon ausgehen, dass ich viele Dinge über den Befehl weiß, den ich wiederholen möchte, was nicht immer der Fall ist.
Fedorqui
Ja ich stimme zu. Es wäre großartig, wenn diese Funktion zum Rückgängigmachen auf zuvor eingegebene Befehle erweitert würde.
Iyrin