Ответ 1
for run in {1..10}
do
command
done
Или в качестве одной строки для тех, кто хочет легко копировать и вставлять:
for run in {1..10}; do command; done
Я иногда запускаю командную строку bash следующим образом:
n=0; while [[ $n -lt 10 ]]; do some_command; n=$((n+1)); done
Чтобы запустить some_command
несколько раз подряд - 10 раз в этом случае.
Часто some_command
- это действительно цепочка команд или конвейер.
Есть ли более краткий способ сделать это?
for run in {1..10}
do
command
done
Или в качестве одной строки для тех, кто хочет легко копировать и вставлять:
for run in {1..10}; do command; done
Используя константу:
for ((n=0;n<10;n++)); do some_command; done
Использование переменной (может включать математические выражения):
x=10 for ((n=0; n < (x / 2); n++)); do some_command; done
Еще один простой способ взломать его:
seq 20 | xargs -Iz echo "Hi there"
выполните эхо 20 раз.
Обратите внимание, что seq 20 | xargs -Iz echo "Hi there z"
будет выводить:
Привет там 1
Привет там 2
...
Если вы используете оболочку zsh:
repeat 10 { echo 'Hello' }
Где 10 - количество повторений команды.
Используя GNU Parallel, вы можете:
parallel some_command ::: {1..1000}
Если вы не хотите, чтобы число как аргумент и выполнялось только одно задание за раз:
parallel -j1 -N0 some_command ::: {1..1000}
Смотрите видеоролик для быстрого введения: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
Пройдите через учебник (http://www.gnu.org/software/parallel/parallel_tutorial.html). Вы в командной строке с любовью к вам за это.
Простая функция в конфигурационном файле bash (часто ~/.bashrc
) может работать хорошо.
function runx() {
for ((n=0;n<$1;n++))
do ${*:2}
done
}
Назови это так.
$ runx 3 echo 'Hello world'
Hello world
Hello world
Hello world
Другая форма вашего примера:
n=0; while (( n++ < 10 )); do some_command; done
xargs
быстро:
#!/usr/bin/bash
echo "while loop:"
n=0; time while (( n++ < 10000 )); do /usr/bin/true ; done
echo -e "\nfor loop:"
time for ((n=0;n<10000;n++)); do /usr/bin/true ; done
echo -e "\nseq,xargs:"
time seq 10000 | xargs -I{} -P1 -n1 /usr/bin/true
echo -e "\nyes,xargs:"
time yes x | head -n10000 | xargs -I{} -P1 -n1 /usr/bin/true
echo -e "\nparallel:"
time parallel --will-cite -j1 -N0 /usr/bin/true ::: {1..10000}
На современном 64-битном Linux дает:
while loop:
real 0m2.282s
user 0m0.177s
sys 0m0.413s
for loop:
real 0m2.559s
user 0m0.393s
sys 0m0.500s
seq,xargs:
real 0m1.728s
user 0m0.013s
sys 0m0.217s
yes,xargs:
real 0m1.723s
user 0m0.013s
sys 0m0.223s
parallel:
real 0m26.271s
user 0m4.943s
sys 0m3.533s
Это имеет смысл, так как команда xargs
- это единственный собственный процесс, который вызывает команду /usr/bin/true
несколько раз, вместо циклов for
и while
, которые все интерпретируются в Bash. Конечно, это работает только для одной команды; если вам нужно выполнить несколько команд в каждой итерации цикла, это будет так же быстро или, может быть, быстрее, чем передача sh -c 'command1; command2; ...'
в xargs
-P1
также можно изменить, скажем, на -P8
, чтобы вызвать 8 процессов параллельно, чтобы получить еще один большой импульс в скорости.
Я не знаю, почему параллель GNU настолько медленная. Я бы подумал, что это будет сопоставимо с xargs.
xargs и seq помогут
function __run_times { seq 1 $1| { shift; xargs -i -- "[email protected]"; } }
вид:
[email protected]:~$ __run_times 3 echo hello world
hello world
hello world
hello world
for _ in {1..10}; do command; done
Обратите внимание на подчеркивание вместо использования переменной.
Во-первых, вы можете обернуть его функцией:
function manytimes {
n=0
times=$1
shift
while [[ $n -lt $times ]]; do
[email protected]
n=$((n+1))
done
}
Назовите его так:
$ manytimes 3 echo "test" | tr 'e' 'E'
tEst
tEst
tEst
Если вы в порядке делаете это периодически, вы можете запустить следующую команду, чтобы запускать ее каждые 1 сек бесконечно. Вы можете поместить другие пользовательские проверки, чтобы запустить его n раз.
watch -n 1 some_command
Если вы хотите визуально подтвердить изменения, добавьте --differences
до команды ls
.
В соответствии с man-страницей OSX также есть
Параметр --кумулятивный делает выделение "липким", представляя показывая все позиции, которые когда-либо менялись. -t или --no-title отключает заголовок, показывающий интервал, команды и текущее время в верхней части дисплея, а также после пустой строки.
Страница руководства Linux/Unix находится здесь
Все существующие ответы, по-видимому, требуют bash
и не работают со стандартным BSD UNIX /bin/sh
(например, ksh
в OpenBSD).
Следующий код должен работать на любом BSD:
$ echo {1..4}
{1..4}
$ seq 4
sh: seq: not found
$ for i in $(jot 4); do echo e$i; done
e1
e2
e3
e4
$
Еще один ответ: используйте расширение параметра для пустых параметров:
# calls curl 4 times
curl -s -w "\n" -X GET "http:{,,,}//www.google.com"
Протестировано на Centos 7 и MacOS.
Я решил с этим циклом, где repeat - целое число, представляющее число циклов
repeat=10
for n in $(seq $repeat);
do
command1
command2
done
Как насчет альтернативной формы for
, упомянутой в (bashref) Looping Constructs?
Для петель, вероятно, правильный способ сделать это, но вот забавная альтернатива:
echo -e {1..10}"\n" |xargs -n1 some_command
Если вам нужен номер итерации в качестве параметра для вашего вызова, используйте:
echo -e {1..10}"\n" |xargs [email protected] echo now I am running iteration @
Изменить:. Было справедливо прокомментировано, что приведенное выше решение будет работать гладко только с простыми запусками команд (без труб и т.д.). вы всегда можете использовать sh -c
, чтобы делать более сложные вещи, но не стоит того.
Другим методом, который я использую, является следующая функция:
rep() { s=$1;shift;e=$1;shift; for x in `seq $s $e`; do c=${@//@/$x};sh -c "$c"; done;}
теперь вы можете назвать его как:
rep 3 10 echo iteration @
Первые два числа задают диапазон. @
будет переведен на номер итерации. Теперь вы можете использовать это и для труб:
rep 1 10 "ls [email protected]/|wc -l"
с указанием количества файлов в каталогах R1.. R10.
Файл script
bash-3.2$ cat test.sh
#!/bin/bash
echo "The argument is arg: $1"
for ((n=0;n<$1;n++));
do
echo "Hi"
done
и выход ниже
bash-3.2$ ./test.sh 3
The argument is arg: 3
Hi
Hi
Hi
bash-3.2$
Немного наивно, но это то, что я обычно помню с головы:
for i in 1 2 3; do
some commands
done
Очень похоже на @joe-koberg ответ. Его лучше, особенно если вам нужно много повторений, мне сложнее вспомнить другой синтаксис, потому что в последние годы я много не использую bash
. Я имею в виду не для скриптов, по крайней мере.