Убедитесь, что на вашем сервере установлен Sendmail.
Если вы проверили свой код и проверили, что там нет ничего плохого, перейдите в / var / mail и проверьте, пуста ли эта папка.
Если он пуст, вам нужно будет сделать:
sudo apt-get install sendmail
, если вы находитесь на сервере Ubuntu.
for i in $(seq 1 $END); do echo $i; done
edit: Я предпочитаю seq
по сравнению с другими методами, потому что я действительно могу его запомнить;)
Другой слой косвенности:
for i in $(eval echo {1..$END}); do
∶
Способ POSIX
Если вы заботитесь о переносимости, используйте пример из стандарта POSIX :
i=2
end=5
while [ $i -le $end ]; do
echo $i
i=$(($i+1))
done
Выход:
2
3
4
5
Вещи, которые не POSIX:
(( ))
без доллара, хотя это общее расширение , как указано самим POSIX .[[
. [
здесь достаточно. См. Также: В чем разница между одиночными и двойными квадратными скобками в Bash? for ((;;))
seq
(GNU Coreutils) {start..end}
и не может работать с переменными, как указано в в руководстве Bash . let i=i+1
: POSIX 7 2. Язык командного командного интерпретатора не содержит слова let
, и он не работает на bash --posix
4.3.42 i=$i+1
, но я не уверен. POSIX 7 2.6.4 Арифметическое расширение гласит: если переменная оболочки x содержит значение, которое образует действительную целочисленную константу, необязательно включающую знак «плюс» или «минус», тогда арифметические разложения «$ ((x) ) "и" $ (($ x)) "должны возвращать одно и то же значение. но чтение в буквальном смысле это не означает, что $((x+1))
расширяется, поскольку x+1
не является переменной. for ((i=$1;i<=$2;++i)); do echo $i; done
в скрипте отлично работает для меня в bash v.4.1.9, поэтому я не вижу проблемы с аргументами командной строки. Вы имеете в виду что-то еще?
– tzot
9 January 2012 в 16:41
time for i in $(seq 100000); do :; done
намного быстрее!
– F. Hauri
2 August 2013 в 05:58
x
, а не ко всему выражению. $((x + 1))
просто отлично.
– chepner
14 October 2016 в 12:12
seq
(BSD seq
позволяет установить строку завершения последовательности с -t
), FreeBSD и NetBSD также имеют seq
с 9.0 и 3.0 соответственно.
– Adrian Günter
23 April 2018 в 18:31
$((x+1))
и $((x + 1))
разыгрываются точно так же, как когда парсер токенизирует x+1
, он будет разбит на 3 жетона: x
, +
и 1
. x
не является допустимым числовым токеном, но он является допустимым токеном имени переменной, но x+
не является, следовательно, разделенным. +
является допустимым токеном арифметического оператора, но +1
не является, поэтому токен снова расщепляется. И так далее.
– Adrian Günter
23 April 2018 в 18:37
Вот почему исходное выражение не сработало.
Из man bash :
Расширение скобки выполняется перед любыми другими расширениями , и в результате сохраняются любые символы, специальные для других расширений. Это строго текстовое. Bash не применяет синтаксическую интерпретацию контекста расширения или текста между фигурными скобками.
blockquote>Итак, расширение скобки - это что-то, сделанное раньше, как чисто текстовое макро-операции, до расширения параметра .
Корпуса представляют собой высоко оптимизированные гибриды между макропроцессорами и более формальными языками программирования. Чтобы оптимизировать типичные варианты использования, язык становится более сложным, и некоторые ограничения принимаются.
Рекомендация
blockquote>Я бы предложил придерживаться Posix1 функции. Это означает использование
for i in <list>; do
, если список уже известен, в противном случае используйтеwhile
илиseq
, как в:#!/bin/sh limit=4 i=1; while [ $i -le $limit ]; do echo $i i=$(($i + 1)) done # Or ----------------------- for i in $(seq 1 $limit); do echo $i done
1. Bash - отличная оболочка, и я использую ее в интерактивном режиме , но я не ставил bash-isms в мои скрипты. Скриптам может понадобиться более быстрая оболочка, более безопасная, более встроенная. Им может потребоваться запустить все, что установлено как / bin / sh, и тогда есть все обычные аргументы pro-standards. Помните shellshock, aka bashdoor?
seq
для больших диапазонов. Например, echo {1..1000000} | wc
показывает, что эхо дает 1 строку, миллион слов и 6 888 896 байт. Попытка seq 1 1000000 | wc
дает миллион строк, миллион слов и 6 888 896 байт, а также более чем в семь раз быстрее, чем измеряется командой time
.
– George
19 January 2015 в 02:52
while
: stackoverflow.com/a/31365662/895245 Но рад, что вы согласитесь :-)
– Ciro Santilli 新疆改造中心 六四事件 法轮功
4 September 2016 в 20:09
Если вам нужен префикс, который вам может понравиться
for ((i=7;i<=12;i++)); do echo `printf "%2.0d\n" $i |sed "s/ /0/"`;done
, который даст
07
08
09
10
11
12
Метод seq
является самым простым, но у Bash есть встроенная арифметическая оценка.
END=5
for ((i=1;i<=END;i++)); do
echo $i
done
# ==> outputs 1 2 3 4 5 on separate lines
Конструкция for ((expr1;expr2;expr3));
работает так же, как for (expr1;expr2;expr3)
на C и подобных языках, и нравится других ((expr))
случаях, Bash рассматривает их как арифметику.
typeset -i i END
. В периоды pre-bash (т. Е. Ksh) это имело значение, но компьютеры были намного медленнее.
– tzot
4 October 2008 в 23:59
seq
. Используй это!
– bobbogo
14 March 2011 в 21:08
#!/bin/bash
первую строку вашего скрипта. [Д0] wiki.ubuntu.com/…
– Melebius
24 April 2017 в 13:22
Если вы используете BSD / OS X, вы можете использовать jot вместо seq:
for i in $(jot $END); do echo $i; done
Это прекрасно работает в bash
:
END=5
i=1 ; while [[ $i -le $END ]] ; do
echo $i
((i = i + 1))
done
Вы можете использовать
for i in $(seq $END); do echo $i; done
Я знаю, что этот вопрос касается bash
, но - только для записи - ksh93
умнее и реализует его, как ожидалось:
$ ksh -c 'i=5; for x in {1..$i}; do echo "$x"; done'
1
2
3
4
5
$ ksh -c 'echo $KSH_VERSION'
Version JM 93u+ 2012-02-29
$ bash -c 'i=5; for x in {1..$i}; do echo "$x"; done'
{1..5}
Если вы выполняете команды оболочки, и у вас (как у I) есть фетиш для конвейерной обработки, это хорошо:
seq 1 $END | xargs -I {} echo {}
Это работает в Bash и Korn, также может идти от более высоких к более низким числам. Наверное, не самый быстрый или красивый, но работает достаточно хорошо. Также обрабатывает негативы.
function num_range {
# Return a range of whole numbers from beginning value to ending value.
# >>> num_range start end
# start: Whole number to start with.
# end: Whole number to end with.
typeset s e v
s=${1}
e=${2}
if (( ${e} >= ${s} )); then
v=${s}
while (( ${v} <= ${e} )); do
echo ${v}
((v=v+1))
done
elif (( ${e} < ${s} )); then
v=${s}
while (( ${v} >= ${e} )); do
echo ${v}
((v=v-1))
done
fi
}
function test_num_range {
num_range 1 3 | egrep "1|2|3" | assert_lc 3
num_range 1 3 | head -1 | assert_eq 1
num_range -1 1 | head -1 | assert_eq "-1"
num_range 3 1 | egrep "1|2|3" | assert_lc 3
num_range 3 1 | head -1 | assert_eq 3
num_range 1 -1 | tail -1 | assert_eq "-1"
}
Это другой способ:
end=5
for i in $(bash -c "echo {1..${end}}"); do echo $i; done
Все это хорошо, но seq предположительно устарел, и большинство из них работают только с числовыми диапазонами.
Если вы заключите цикл for в двойные кавычки, стартовые и конечные переменные будут разыменованы, когда вы будете эхо-строки , и вы можете отправить строку обратно в BASH для выполнения. $i
должен быть экранирован, поэтому он НЕ оценивается перед отправкой на подоболочку.
RANGE_START=a
RANGE_END=z
echo -e "for i in {$RANGE_START..$RANGE_END}; do echo \\${i}; done" | bash
Этот вывод также может быть назначен переменной:
VAR=`echo -e "for i in {$RANGE_START..$RANGE_END}; do echo \\${i}; done" | bash`
Единственный «служебный» ресурс, который должен генерировать, должен быть вторым экземпляром bash, поэтому он должен быть подходящим для интенсивных операций.
Заменить {}
на (( ))
:
tmpstart=0;
tmpend=4;
for (( i=$tmpstart; i<=$tmpend; i++ )) ; do
echo $i ;
done
Выход:
0
1
2
3
4
Если вы хотите как можно ближе подойти к синтаксису выражения, попробуйте функцию range
из bash-трюков range.bash
.
Для Например, все следующие будут делать то же самое, что и echo {1..10}
:
source range.bash
one=1
ten=10
range {$one..$ten}
range $one $ten
range {1..$ten}
range {1..10}
Он пытается поддерживать собственный синтаксис bash с максимально возможным количеством «gotchas»: поддерживаются не только переменные, но часто нежелательное поведение недопустимых диапазонов, предоставляемых как строки (например, for i in {1..a}; do echo $i; done
), также предотвращается.
Другие ответы будут работать в большинстве случаев, но все они имеют по крайней мере одно из следующих Недостатки:
seq
представляет собой двоичный файл, который должен быть установлен для использования, должен быть загружен bash и должен содержать ожидаемую программу, чтобы он работал в этом случае. {a..z}
; расширение скобки будет. Вопрос был о диапазонах номеров , хотя это так. {1..10}
, поэтому программы, которые используют оба варианта, могут быть немного труднее читать. $END
не является допустимым диапазоном «bookend» для другая сторона диапазона. Если END=a
, например, ошибка не будет выполнена, и будет передано дословное значение {1..a}
. Это также поведение Bash по умолчанию - это просто неожиданно. Отказ от ответственности: я являюсь автором связанного кода.
seq $END
будет достаточным, поскольку по умолчанию должно начинаться с 1. Изman seq
: «Если FIRST или INCREMENT опущено, по умолчанию оно равно 1». – fedorqui 5 August 2014 в 10:06