Я пытался сделать очень простой bash-скрипт для перечисления всех пятикратных чисел между 375 и 3500 (375, 380, 385 ...). Одна вещь, которую я пробовал и не работал:
for i in {375..3500}
do
echo $i
(($i += 5))
done
Через некоторое время я сдался и написал это на бейсике примерно через 15 секунд:
10 count = 375
20 print count
30 count = count+5
40 if count < 3500 then goto 20
Как я могу сделать свою БАЗОВУЮ программу в bash-скрипте?
Ответы:
В качестве альтернативы можно использовать традиционный C-стиль для цикла:
Это, возможно, менее понятно, чем использование seq, но не порождает никаких подпроцессов. Хотя, поскольку я знаком с C, у меня не возникнет никаких затруднений с пониманием этого, кроме YMMV.
источник
dash
, не поддерживает его. @ChrisDown - нет никаких причин, почему «POSIX sh» должен подразумевать «no seq». Но да, конечно, я упустил из виду тот факт, что seq не указан в POSIX.Так как вы все равно используете расширение скобок, полностью используйте его функцию:
Вы также можете использовать эту технику для печати каждого числа в отдельной строке с необязательным текстом, используя
printf
вместоecho
, например:редактировать
Как отметил @kojiro в комментарии, Mac OS использует bash 3 в качестве оболочки по умолчанию, которая не поддерживает приращение в выражении последовательности расширения скобки. Вам необходимо обновить Bash до версии 4 или использовать другую оболочку, которая поддерживает это (например, недавняя zsh).
источник
bash -c
значительной степени гарантирует участие двух разных оболочек. Говорит ли$SHELL --version
это, что это Bash 3?bash
была представлена эта функция. Я узнал это сам из комментариев Кодзиро. И, пожалуйста, не сравнивайте меня с СЦ, я действительно не знаю всех деталей и истории всех оболочек с конца 1970 года. Еще раз - если вы этого ожидаете, просто, пожалуйста, понизьте.Использование SEQ (1)
Или просто:
источник
seq 375 5 3500
.Ваш фрагмент цикла for не работает, как вам требуется по двум причинам:
(($i += 5))
- здесь$i
расширяется до значенияi
. Таким образом, расширение будет чем-то вроде этого((375 += 5))
, что не имеет смысла (попытка присвоить литеральное число другому литеральному номеру). Обычно это достигается с помощью((i += 5))
(нет,$
чтобы расширить переменную){375..3500}
Будет расширен до первой итерации цикла. Это будет список номеров375 376 ... 3499 3500
. Для каждой итерации цикла,i
будут присваиваться каждому из этих номеров, один за другим. Таким образом, в начале каждой итерацииi
будет переназначаться следующее значение в этом списке, считая с шагом 1.((i += 5))
Фактически ничего не делает - он добавляет 5 к i, но затем я просто переназначается снова в начале Следующая итерация.Я думаю, что мне больше нравится
for (( ; ; ))
ответ, но вот несколько вариантов, чтобы вы думали:Поскольку мы имеем дело с коэффициентами, кратными 5, и
{a..b..i}
расширение не поддерживается в bash версии 3.2.57 (1) (в OS X), то вместо этого мы можем сделать это немного загадочно:Это демонстрирует, как bash может быть использован для создания декартового произведения.
В общем, я думаю, что цикл for является наиболее удобным способом сделать это, но если вам интересно, вы можете использовать цикл while (немного ближе к вашему БЕЙСИКУ):
источник
38
до349
. На втором только два номера:0
а5
. Теперь давайте создавать упорядоченные пары этих всех комбинаций - вы можете написать их как наборы:{38,0}
,{38,5}
...{349,5}
, или просто удалить лишние символы{
,,
а}
и получить новые номера ...380
...3495
.Хотя, конечно, есть приложение для этого (
seq 375 5 3500
), есть разные способы сделать это из командной строки. Хотя самый быстрый и простой будет только использоватьseq
, вот некоторые другие варианты:источник
$(($i % 5))
можно написать$((i % 5))
.POSIXly:
...или...
Я не знаю, почему ты сделал это по-другому. За исключением, конечно ...
... или с
dc
:источник
dc
работает код. Это, конечно, более интригующе, чем использованиеseq
.s
сохраняет[
строку]
в верхней частиp
массива, затемl
возвращает ее обратно в начало стека иx
извлекает ее как макрос. Внутри макроса мы помещаем5
стек в стек, затем извлекаем его, а второй сверху и+
их, заменяя оба значения стека их суммой, котораяp
набирается иd
дублируется до того , как она помещается3500
в стек, когда мы вытолкаем его и дупе , который мы только что сделали для сравнение>
. Если3500
больше, мы загружаем и выполняем в качестве макроса строку, хранящуюся вp
массиве (наш текущий макрос) , или, если не, разбиваем.Если вы застряли на Bash 3:
и если вы предпочитаете
awk
:Я не знал о расширении скобок - это действительно круто.
источник