Wiederholen Sie den letzten Befehl N-mal

7

Wenn Sie keine Schleife schreiben, können Sie den letzten Befehl N-mal wiederholen.

Zum Beispiel kann ich den letzten Befehl einmal mit einem Doppelknall (!!) wiederholen, aber wie wiederhole ich ihn 30 Mal?

Tyler Durden
quelle

Antworten:

9

Mit zshund unter der Voraussetzung der letzte Befehlszeile war nur ein Befehl oder eine Pipeline oder und-oder die Liste (das ist zum Beispiel echo x, echo x | tr x y, echo x && echo y, auch Verbindung Befehle wie { x; y; }oder for/ whileSchleifen , aber nicht echo x; echo y):

repeat 30 !!

Verwenden Sie Folgendes, um die vorherige Befehlszeile zu wiederholen, auch wenn sie mehrere Befehle enthielt:

repeat 30 do !!; done

Oder:

repeat 30 {!!}

Mit bashund nur für einfache Befehle (unter den obigen Beispielen nur für den echo xFall) können Sie eine Hilfsfunktion wie folgt definieren:

repeat() {
  local n="$1"
  shift
  while ((n-- > 0)); do
    "$@"
  done
}

(und repeat 30 !!wie oben verwenden). Ein Nebeneffekt ist, dass der Code, da er in einer Funktion ausgeführt wird, anders "$@"aussieht "$#"und Dinge wie typesetanders funktionieren, sodass Sie Dinge wie:

eval 'echo "$1"'
repeat 30 !!

Ein weiterer Ansatz zur emulieren zsh‚s repeat 30 {!!}wäre ein Alias zu erklären , wie:

alias repeat='for i in $(seq'

(unter der Annahme eines unveränderten $IFS)

Und dann benutze:

repeat 30); { !!; }
Stéphane Chazelas
quelle
8

Das kürzeste, was ich mir einfallen lassen kann, ist:

date # or whatever command
for i in {1..30}; do !!; done
Jeff Schaller
quelle
2
Das hat eine Schleife.
Tyler Durden
5
Sie können es auffor i in {1..30};{ !!;}
Stéphane Chazelas
3

Ein Ansatz könnte darin bestehen, den Zeileneditor !!;30 Mal einzufügen .

Wie bei readline( bash's Zeileneditor) im viModus:

!!; Escdd30p

Das emacsModusäquivalent funktioniert mit dem zshZeileneditor, aber anscheinend nicht mit bash's readline. Sie können jedoch readlinestattdessen kbd-Makros verwenden, die anscheinend wiederholt werden können:

Definieren Sie das kbd-Makro wie folgt !!;:

Ctrl+X(!!; Ctrl+X)

Was Sie später 30 Mal aufrufen können als:

Alt+3Alt+0Ctrl+Xe
Stéphane Chazelas
quelle
1

Das ist ein bisschen hässlich, aber:

 eval "`fc -ln -1`;: "{1..10}\;

Das führende Leerzeichen ist nicht unbedingt erforderlich, aber nützlich, um die Eingabe des evalBefehls in den Verlauf zu unterdrücken, wenn es (oder ) $HISTCONTROLenthält .ignorespaceignoreboth

Alternative:

eval "fc -s $((HISTCMD-2)) "{1..10}\;

Und:

eval 'history -s '{1..10}';fc -s -2;'
ecatmur
quelle
0

Der seqBefehl ist Teil von Standard * nix und daher nicht von Ihrer Shell abhängig. Mit ihm und dem Loop-Konstrukt Ihrer Shell können Sie Folgendes tun:

for i in $(seq 30); do !!; done

oder

for i in `seq 30`; do !!; done

Immer lernen
quelle
0

Eine weitere Schleife in Bash (zB danach: https://unix.stackexchange.com/a/372487/9689 )

Machen Sie es irgendwo in Ihrem $PATHNamen repeatzu einer ausführbaren Datei , um einen ähnlichen Effekt wie in zsh zu erzielen ( https://unix.stackexchange.com/a/372484/9689 ):

#!/bin/bash

n=$1
shift 1

for ((x=0; x<$n; ++x)); do
  "$@"
done

so später können Sie:

$ repeat 3 date

Kern: https://gist.github.com/gwpl/26fefe3a165304f3dedb21009506107f

Grzegorz Wierzowiecki
quelle