Ich führe gelegentlich eine Bash-Befehlszeile wie folgt aus:
n=0; while [[ $n -lt 10 ]]; do some_command; n=$((n+1)); done
some_command
Mehrmals hintereinander ausführen - in diesem Fall zehnmal.
Oft some_command
ist es wirklich eine Befehlskette oder eine Pipeline.
Gibt es eine präzisere Möglichkeit, dies zu tun?
let ++n
anstelle vonn=$((n+1))
(3 Zeichen weniger) verwenden.zsh
hatrepeat 10 do some_command; done
.sh: 1: [[: not found
.Antworten:
Oder als Einzeiler für diejenigen, die einfach kopieren und einfügen möchten:
quelle
for (n=0;n<k;n++))
möglicherweise besser. Ich vermute,{1..k}
dass eine Zeichenfolge mit all diesen durch Leerzeichen getrennten Ganzzahlen materialisiert wird.n=15;for i in $(seq -f "%02g" ${n});do echo $i; done 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15
Verwenden einer Konstante:
Verwenden einer Variablen (kann mathematische Ausdrücke enthalten):
quelle
x=10
for ((n=0; n < $x; n++));
for run in {1..10}; do echo "on run $run"; done
n
bereits ein bestimmter Wert festgelegt ist?for (( ; n<10; n++ ))
funktioniert nicht / bearbeitet: Verwenden Sie am besten eine der anderen Antworten wie diewhile (( n++...
eineEin weiterer einfacher Weg, um es zu hacken:
Echo 20 Mal ausführen.
Beachten Sie, dass
seq 20 | xargs -Iz echo "Hi there z"
Folgendes ausgegeben werden würde:quelle
seq 20
)seq 20 | xargs -I{} echo "Hi there {}"
z
kein guter Platzhalter ist, da er so häufig ein normaler Text im Befehlstext sein kann. Verwendung{}
wird besser sein.seq
? also würde es nurHi there
20 mal drucken (keine nummer)? BEARBEITEN: einfach verwenden-I{}
und dann keine{}
im Befehl habenIIIII
sieht es zum Beispiel gut aus:seq 20 | xargs -IIIIII timeout 10 yourCommandThatHangs
Wenn Sie die zsh-Shell verwenden:
Dabei ist 10 die Häufigkeit, mit der der Befehl wiederholt wird.
quelle
repeat 10 { !! }
Mit GNU Parallel können Sie Folgendes tun:
Wenn Sie die Nummer nicht als Argument verwenden und jeweils nur einen Job ausführen möchten:
Sehen Sie sich das Intro-Video für eine kurze Einführung an: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
Gehen Sie durch das Tutorial ( http://www.gnu.org/software/parallel/parallel_tutorial.html ). Sie Kommandozeile mit Liebe Sie dafür.
quelle
-j1 -N0
dass wiederum von der Parallelität ????some_command
1000 Mal in Serie ohne Argumente laufen ? Und: Kannst du das kürzer ausdrücken alsparallel -j1 -N0 some_command ::: {1..1000}
?repeat.sh repeatcount some_command
. Für die Implementierung im Shell-Skript könnte ich verwendenparallel
, wenn es bereits auf dem Computer installiert war (wahrscheinlich nicht). Oder ich mag Xargs, da dies am schnellsten zu sein scheint, wenn keine Umleitung von erforderlich istsome_command
.parallel -N0 -j1 --retries 4 --results outputdir/ some_command
Eine einfache Funktion in der Bash-Konfigurationsdatei (
~/.bashrc
oft) könnte gut funktionieren.Nennen Sie es so.
quelle
do ${*:2}
eval hinzuzufügendo eval ${*:2}
, um sicherzustellen, dass es zum Ausführen von Befehlen funktioniert, die nicht mit ausführbaren Dateien beginnen. Zum Beispiel, wenn Sie eine Umgebungsvariable festlegen möchten, bevor Sie einen Befehl wie ausführenSOME_ENV=test echo 'test'
.xargs
ist schnell :Auf einem modernen 64-Bit-Linux gibt es:
Dies ist sinnvoll, da der
xargs
Befehl ein einzelner nativer Prozess ist, der den/usr/bin/true
Befehl mehrmals erzeugt, anstelle derfor
und-while
Schleifen, die alle in Bash interpretiert werden. Dies funktioniert natürlich nur für einen einzelnen Befehl. Wenn Sie in jeder Iteration der Schleife mehrere Befehle ausführen müssen, ist diese genauso schnell oder möglicherweise schneller als die Übergabesh -c 'command1; command2; ...'
an xargsDas
-P1
könnte auch geändert werden,-P8
um beispielsweise 8 Prozesse parallel zu erzeugen, um einen weiteren großen Geschwindigkeitsschub zu erzielen.Ich weiß nicht, warum GNU parallel so langsam ist. Ich hätte gedacht, es wäre vergleichbar mit Xargs.
quelle
Eine andere Form Ihres Beispiels:
quelle
Zum einen können Sie es in eine Funktion einschließen:
Nennen Sie es wie:
quelle
tr
hier ist irreführend und es arbeitet an der Ausgabe vonmanytimes
, nichtecho
. Ich denke, Sie sollten es aus der Probe entfernen.xargs und seq werden helfen
die Aussicht :
quelle
Beachten Sie den Unterstrich, anstatt eine Variable zu verwenden.
quelle
_
ist ein Variablenname.Wenn Sie dies regelmäßig tun, können Sie den folgenden Befehl ausführen, um es alle 1 Sekunde auf unbestimmte Zeit auszuführen. Sie können andere benutzerdefinierte Überprüfungen einrichten, um sie n-mal auszuführen.
watch -n 1 some_command
Wenn Sie eine visuelle Bestätigung der Änderungen wünschen, fügen Sie diese
--differences
vor demls
Befehl hinzu.Laut der OSX-Manpage gibt es auch
Die Linux / Unix-Manpage finden Sie hier
quelle
Ich habe mit dieser Schleife gelöst, wobei Wiederholung eine Ganzzahl ist, die die Nummer der Schleifen darstellt
quelle
Noch eine Antwort: Verwenden Sie die Parametererweiterung für leere Parameter:
Getestet auf Centos 7 und MacOS.
quelle
Alle vorhandenen Antworten scheinen erforderlich zu sein
bash
und funktionieren nicht mit einem Standard-BSD-UNIX/bin/sh
(z. B.ksh
unter OpenBSD ).Der folgende Code sollte auf jedem BSD funktionieren:
quelle
Ein bisschen naiv, aber das ist es, woran ich mich normalerweise auf Anhieb erinnere:
Sehr ähnlich zu @ joe-kobergs Antwort. Seine ist besser, besonders wenn Sie viele Wiederholungen benötigen, nur schwieriger für mich, mich an andere Syntax zu erinnern, weil ich in den letzten Jahren nicht
bash
viel benutze . Ich meine zumindest nicht für Skripte.quelle
Die Skriptdatei
und die Ausgabe unten
quelle
Wie wäre es mit der alternativen Form der
for
in (bashref) Looping Constructs erwähnten ?quelle
For-Loops sind wahrscheinlich der richtige Weg, aber hier ist eine unterhaltsame Alternative:
echo -e {1..10}"\n" |xargs -n1 some_command
Wenn Sie die Iterationsnummer als Parameter für Ihren Aufruf benötigen, verwenden Sie:
echo -e {1..10}"\n" |xargs -I@ echo now I am running iteration @
Bearbeiten: Es wurde zu Recht kommentiert, dass die oben angegebene Lösung nur mit einfachen Befehlsläufen (keine Pipes usw.) reibungslos funktionieren würde. Sie können immer eine verwenden
sh -c
, um kompliziertere Dinge zu tun, aber es lohnt sich nicht.Eine andere Methode, die ich normalerweise verwende, ist die folgende Funktion:
rep() { s=$1;shift;e=$1;shift; for x in `seq $s $e`; do c=${@//@/$x};sh -c "$c"; done;}
Jetzt können Sie es nennen als:
rep 3 10 echo iteration @
Die ersten beiden Zahlen geben den Bereich an. Das
@
wird in die Iterationsnummer übersetzt. Jetzt können Sie dies auch mit Rohren verwenden:rep 1 10 "ls R@/|wc -l"
mit geben Sie die Anzahl der Dateien in den Verzeichnissen R1 .. R10.
quelle
rep 1 2 touch "foo @"
erstellt nicht zwei Dateien "foo 1" und "foo 2"; Vielmehr werden drei Dateien "foo", "1" und "2" erstellt. Es mag eine Möglichkeit geben, das Zitat mitprintf
und richtig zu zitieren%q
, aber es wird schwierig sein, eine beliebige Folge von Wörtern korrekt in eine einzelne Zeichenfolge zu zitieren, an die übergeben werden sollsh -c
.rep
in Ihrem definiert haben.bashrc
, werden weitere Aufrufe viel präziser.