LINUX.ORG.RU

Как добавить в скрипт цикл if?

 ,


0

1

Основной рабочий скрипт

ping -c 1 ubuntu.com > /dev/null
if [ $? -eq 0 ]; then

   date=$(date -u +'%d%m%Y')
   for n in $(echo one two three); do
       echo $n
   done
   for n in $(echo bullseye jammy xenial); do

       if [ $n != bullseye ]; then
         echo "it's ubuntu"
       else
         echo "it's debian"
       fi

   done
fi

Дополнительный цикл, который нужно добавить (без функций):

   if [ $(date -u +'%d') -eq 28 ]; then

       for n in $(echo bullseye jammy xenial); do
         echo "OS name: $n"

       done

   fi

Пробовал добавить его после …."echo «it’s debian» fi done

или после всего, но цикл не срабатывал, как будто его нет.

Ответ на: комментарий от anonymous

Пробовал добавлять вот так:

ping -c 1 ubuntu.com > /dev/null
if [ $? -eq 0 ]; then

   date=$(date -u +'%d%m%Y')
   for n in $(echo one two three); do
       echo $n
   done
   for n in $(echo bullseye jammy xenial); do

       if [ $n != bullseye ]; then
         echo "it's ubuntu"
       else
         echo "it's debian"
       fi

   done
# Вот тут 
   if [ $(date -u +'%d') -eq 28 ]; then
       for n in $(echo bullseye jammy xenial); do
         echo "OS name: $n"
       done
   fi

fi
# И вот тут
if [ $(date -u +'%d') -eq 28 ]; then
    for n in $(echo bullseye jammy xenial); do
      echo "OS name: $n"
    done
fi
chart41
() автор топика

но цикл не срабатывал, как будто его нет

Число не 28-ое?

А вообще, это чё-то на баш не похоже. Я б так:

ping -c1 ubuntu.com > /dev/null

if (($? == 0)); then
    date=$(date -u +'%d%m%Y')
    for n in {one,two,three}; do
        echo $n
    done
    for n in {bullseye,jammy,xenial}; do
        if [[ $n != bullseye ]]; then
            echo it\'s ubuntu
        else
            echo it\'s debian
        fi
    done
fi

if (($(date -u +'%d') == 28)); then
    for n in {bullseye,jammy,xenial}; do
        echo OS name: $n
    done
fi

и да, покажи весь скрипт и расскажи чего хочешь сделать.

papin-aziat ★★★★★
()

Начнём с того if это не цикл.

Дополнительный цикл, который нужно добавить (без функций):

Ну так добавь. В чём проблема?

или после всего, но цикл не срабатывал, как будто его нет.

Ты бы описал чего ты хочешь добиться. В текущем виде твоя задача выглдяит так: «хочу вставить в скрипт какие-то строчки» и больше ничего не требуется. Для этого нужен текстовый редактор и всё.

firkax ★★★★★
()
Ответ на: комментарий от papin-aziat

Скобки — это хорошо! Но справа налево читать не преучен. Не семит какой. Так что из тезиса с антитезисом получается синтез

user> (-> (pipeline 
           (pb "echo foo bar") 
           (pb "grep foo") 
           (pb "cut -d' ' -f2")) 
          last :out slurp)
"bar\n"
user> 
ugoday ★★★★★
()

Вау, кажется мне потребуется час чтобы понять что ты пытался сделать. Например

for n in $(echo one two three); do
       echo $n
   done
кажется предназначено для разворачивания надписи построчно, т.е. проще было бы echo one; echo two; echo three. А ещё этот кусок не несёт никакой смысловой нагрузки...

kirill_rrr ★★★★★
()
Ответ на: комментарий от ugoday

лишний <

Чем докажешь? Я вот, допустим, не знаю как ведёт себя этот cut, когда читает файл. Например бывает такое:

wс -l foo.txt
100500 foo.txt # упс
wc -l < foo.txt
100500 # збсь!

Потом, в конвеере ж передавалось на stdin, так что…

Но я шуткую и ты конечно прав.

papin-aziat ★★★★★
()
Ответ на: комментарий от papin-aziat

Чем докажешь?

А это возвращает нас к старому спору о баше: он позволяет очень компактно описать довольно сложные штуки, но ценой превращения кода в нечитаемую лапшу из специальных символов и значимых пробелов. Хуже этого только YAML (он заодно и популярнее).

ugoday ★★★★★
()

Избыточно.

Вот так покороче, и 28-го числа дождитесь:

#!/bin/sh

list="bullseye jammy xenial"

ping -c 1 ubuntu.com >/dev/null && {
  echo -e "one\ntwo\nthree"
  for n in $list ; do
    test "X$n" != "Xbullseye" && echo "it's ubuntu" || { 
      echo "it's debian" ; 
      test $(date -u +'%d') -eq 28 && for k in $list ; do echo "OS name: $k" ; done ;
    }
  done
}

P.S. поправил ‘\n’, где надо. И имена переменных еще.

x22 ★★
()
Последнее исправление: x22 (всего исправлений: 2)
Ответ на: комментарий от ugoday

ценой превращения кода в нечитаемую лапшу

В примере выше виновата программа wc, bash-то не при чём.

из специальных символов и значимых пробелов

В каком смысле «значимых»?

papin-aziat ★★★★★
()
Ответ на: комментарий от papin-aziat

виновата программа wc, bash-то не при чём.

а баш без внешних программ никому и не нужен

В каком смысле «значимых»?

Вот так правильно: if [[ $n != bullseye ]]; then. Вот так неправильно: if [[ $n != bullseye]]; then. Тут икс равен единице: x=1. А тут не равен: x= 1.

ugoday ★★★★★
()
Ответ на: комментарий от ugoday

Вот так правильно: if [[ $n != bullseye ]]; then. Вот так неправильно: if [[ $n != bullseye]]; then.

А разве в других языках нет особенностей, которые были бы следствием уже занятых комбинаций?

Здесь, думаю, чтобы избежать противоречия между [ & [[ и диапазонами символов, ведь шелл умеет в globbing & wildcard. То же самое, наверное, с фигурными скобками в объединении команд и цикле for (который в стиле Си), где надо обязательно использовать пробелы (ещё и точку с запятой), если в одной строке с командами.

Не много ведь надо запомнить! Ну, ещё, что нельзя ставить пробелы в перенаправлениях с помощью дескрипторов :-)

Тут икс равен единице: x=1. А тут не равен: x= 1.

Такая вот тема с разбиением на слова, надо чтобы было одним словом. Однако, для манипуляции с числами надо использовать (()), и всё будет отлично, кстати, и читабельность кода вырастет — видишь скобки, значит математика 😀

$ unset x
$ ((x= 1))
$ echo $x
1

там всё по-человечески: =, ==, !=, <, >, <=, >=, etc, а не эти ужасные -lt, -gt, -eq, etc. И пробелы сколько хочешь ставь или не ставь совсем 😀

papin-aziat ★★★★★
()
Ответ на: комментарий от papin-aziat

А разве в других языках нет особенностей,

Вот, чтобы x=1 и x= 1 различался, я, пожалуй, нигде больше не припомню. В тех же сях if (x=1) может оконфузить, но уж if (x == 1) и if (x == 1 ) работают строго одинаково.

следствием уже занятых комбинаций?

Ну, вопрос был про значимые пробелы, я и ответил.

Не много ведь надо запомнить!

Да просто не ошибайтесь, тогда и ошибок не будет.

ugoday ★★★★★
()
Ответ на: комментарий от ugoday

но ценой превращения кода в нечитаемую лапшу из специальных символов и значимых пробелов

Только если этот шелл на самом деле подражает перлу и пытается под каждую новую проблему выдумать новую конструкцию. Привет, баш. Если не выходить за рамки проблемы «запуск программ», то шелл выглядит довольно аккуратно.

kaldeon
()
Ответ на: комментарий от ugoday

А данные, ведь ты же как-то должен думать о том, с чем имеешь дело, или где-то можно совсем от всего абстрагироваться?

В шелле — это текстовая строка, состоящая из слов. Пробел, табуляция и перевод строки являются разделителями слов, то есть по сути метасимволами, которые надо экранировать, если хочешь использовать. Шелл читает строку и разбивает на слова, которые становятся его аргументами. Например, программа или функция не может же иметь пробельные символы в названии и нет никаких проблем, никто не жалуется, так вот и в работе с переменными так же, если с ними работаешь прямо в строке шелла (скрипт — та же строка), а не в $(()), (()) или for ((;;))..., то есть в специальных конструкциях для арифметики. По сути внутри каждой конструкции своеобразная логика и без бутылки (без ящика) там не разобраться, да, но мне никак не понятно, что тут напрягает опытных программистов, у которых в голове по десять-двадцать языков, всяких там разметок и тд.

papin-aziat ★★★★★
()
Ответ на: комментарий от papin-aziat

Однако, для манипуляции с числами надо использовать (()), и всё будет отлично, кстати, и читабельность кода вырастет — видишь скобки, значит математика 😀

Для работы с числами можно использовать bc, внезапно. Основная задача шелла — запуск программ, bc — программа, работающая с числами. Идеальный мэтч.

Но мы же слишком гордые. Перл смог без внешних программ решить эту проблему, со всеми вытекающими преимуществами (ну эффективность, например), а мы чем хуже? Надо повторить.

kaldeon
()
Последнее исправление: kaldeon (всего исправлений: 2)
Ответ на: комментарий от papin-aziat

Раз, два, три, четыре, 5. Вместо «5» больше подходит «пять». Вот и там по этой же причине я сделал echo -n и явно указал последний line feed. =]

kaldeon
()
Последнее исправление: kaldeon (всего исправлений: 1)
Ответ на: комментарий от papin-aziat

Heredoc-и выглядят сложнее, чем обычный echo. Мне кажется, они лучше подходят для текстов бòльшего объёма или где не хочется париться про наличие синтаксических конструкций в данных. Например, внезапный ' не сломает скрипт. Можно спокойно вставить кусок JSON-а в скрипт, не опасаясь неожиданного поведения.

“Make the common cases easy.”

kaldeon
()
Последнее исправление: kaldeon (всего исправлений: 3)
Ответ на: комментарий от papin-aziat

Безусловно любая система основана на каких-то решениях и компромиссах, каковые в некоторых краевых случаях выходят боком и программисту нужно об этом помнить, знать основные проблемы и пути их обхода. Но. Тут мы наблюдаем диалектический закон перехода количества в качество в действии. Одно дело гулять по парку, где местами дорожки от листьев не убраны или корни торчат, споткнуться можно. Другое — бродить сталкером по Зоне.

мне никак не понятно, что тут напрягает опытных программистов

Кроме практического аспекта: очень страдает эстетическое чувство. В С занимаешься низкоуровневой долбнёй хотя бы понятно зачем (паскаль спроектирован лучше, но …). А тут — непонятно. Из-за кривого дизайна приходится постоянно напрягаться, делать специальные приседания и держать в уме кучу деталей и особенностей поведения уровня «если с ними работаешь прямо в строке шелла (скрипт — та же строка), а не в $(()), (())», а что я за это получаю? Везде я могу сравнить два числа и две строки одним и тем же if x<y выражением и всё отлично работает, а здесь — фигушки. За что мне такое наказание?

Программируя на баше, начинаешь чувствовать себя глупо. И это напрягает опытных программистов.

ugoday ★★★★★
()
Ответ на: комментарий от kaldeon

Если не выходить за рамки проблемы «запуск программ», то шелл выглядит довольно аккуратно.

Да хрен там плавал. Аккуратно получается только если писать скрипт так же, как мы пишем команды в диалоговом режиме. Однако в оном режиме мы можем очень сильно упростить себе жизнь, например, нам не нужен интерфейс пользователя, он сам себе интерфейс, нам не нужно проверять входные значения, они и так перед глазами, обрабатывать ошибки и т.п. Получается, краткая, радующая глаз запись. Которая рухнет, разнося всё вокруг, из-за «неправильного» файла, если запустить скрипт на другой машине или над другими данными.

ugoday ★★★★★
()
Ответ на: комментарий от ugoday

За что мне такое наказание? Программируя на баше

Мне кажется, корень всех зол в том, что инструменты используют не по назначению. Баш - это не средство программирования, и тот факт что его таковым сделали, никак не оправдывает применение баша для написания программ. Для шелла хорошо подходит простой безтиповый REPL интерпретатор, и sh и его деривативы задумывались для сугубо пользовательских целей - для запуска приложений и простой настройки операционной системы, а не для сложных административных задач. Когда все эти шеллы придумывали, командная строка была единственным интерфейсом взаимодействия с ОС. На практике же оказалось, что юзерам удобнее работать с графическим/тексто-графическим интерфейсом, а командная строка стала инструментом админа. Админы стали использовать знакомый им язык для автоматизации задач, развивая синтаксис командной строки в полноценный ЯП. Теперь мы имеем баш-портянки, с которыми психически здоровому программисту работать больно.

FishHook
()
Ответ на: комментарий от papin-aziat

Продолжу нести свет истинной веры развивать гнусную башефобию общение. Вот, вы говорите

В шелле — это текстовая строка, состоящая из слов.

А ведь это не так. Текстовая строка состоит из неких выражений командного мини-языка, которые в простейшем случае тождественны словам.

Например в mkdir -p {eu,uk,us}/{dev,stage,prod} у нас сначала идёт интерпретация по особым правилам, а потом уже разбиение строки на слова, разделённые пробелами. И в этом корень зла. Строка, базовая абстракция пути юникса, протекает со страшной силой. Вот, выше предлагалось сравнивать строки, предварительно добавив к ним одинаковые префиксы

test "X$n" != "Xbullseye" && echo "it's ubuntu" 

Вот, откуда это пошло, что это за бред вообще? А это шелл так устроен, что он сначала раскрывает переменные в строки, а уже потом пытается понять, что здесь оператор, а что операнд. (И там в солярке и других древних юниксах в некоторых случаях возникала какая-то неоднозначность, которую можно убрать с помощью трюка с префиксами и мы все вынуждено до сих пор терпеть это безобразие, потому что ничего не поделаешь, это баш).

Вы на это можете возразить, что в том же лиспе есть макросы и они тоже используют свою семантику и каждый макрос это отдельный мини-язык, который нужно отдельно и изучать. И это так. Но в лиспе область хаоса контролируется скобками. loop может извращаться со своими аргументами как угодно, наружу это не выйдет. Никому не придёт в голову экранировать все "$variable" потому что где-то выше по коду или в библиотеках используется loop/iterate/with-*. Хорошо бы и в шелле иметь возможность разделять на типы данных: строка как простая последовательность символов и строка как встроенная мини-программа. Но пока имеем, что имеем.

ugoday ★★★★★
()
Ответ на: комментарий от ugoday

Продолжу

Поддержу, но надо держать в голове, что я всего лишь прочитал пару книг про Bash-4, поэтому мои рассуждения носят сугубо спекулятивный характер и к тому же всё осложняется моей полной технической безграмотностью 😁

А ведь это не так. Текстовая строка состоит из неких выражений командного мини-языка, которые в простейшем случае тождественны словам. Например в mkdir -p {eu,uk,us}/{dev,stage,prod} у нас сначала идёт интерпретация по особым правилам, а потом уже разбиение строки на слова, разделённые пробелами.

Тогда уж мини-языков, впрочем, их, кажется, всего три: подстановка путей, раскрытие фигурных скобок и этакий «язык переменных», а разбиение на слова, это типа фильтр, типа кто не спрятался (не экранирован), я не виноват :-)

Понимаю, что, наверное, говорю чепуху, но мне проще отнести к мини-языку переменных (я про возможность редактирования подстановок без использования cut или sed) и заключение их в кавычки, ибо этот синтаксис надо знать отдельно: $*, $@ — одинаковый результат, а "$*" и "$@" — разный. То же самое с массивами.

Если уж докапываться до мини-языков, то тогда уж до regex-ов, но ты почему-то на эту тему молчишь…

test «X$n» != «Xbullseye» && echo «it’s ubuntu», Вот, откуда это пошло, что это за бред вообще?

Это какое-то заклинание древних магов борновского шелла. Сегодня не актуально. Ключевое слово [[ решает это без запинки: [[ $n != bulllseye ]], всё, $n может быть пустым или содержать пробельные символы, неважно, даже кавычки не нужны.

А это шелл так устроен, что он сначала раскрывает переменные в строки, а уже потом пытается понять, что здесь оператор, а что операнд.

А как иначе, если, например, ты хочешь сохранить в переменную команды и потом их подставить? Никто же не жалуется, что (2*2+2)=(2+2*2), поэтому такие вещи надо учить как ни крути, иначе где-нибудь обязательно бахнет.

И там в солярке и других древних юниксах в некоторых случаях возникала какая-то неоднозначность, которую можно убрать с помощью трюка с префиксами и мы все вынуждено до сих пор терпеть это безобразие, потому что ничего не поделаешь, это баш

Не, не надо больше терпеть, это не баш (может быть какой-нибудь древний баш, хз). Bash, как я понимаю, постоянно всё упрощает и добавляет фичи. Вот, кстати, прочитал сегодня, что в пятом по умолчанию активируют globasciirange, а мне самому это надо делать или использовать LANG=POSIX или LANG=C.UTF-8, иначе при использовании диапазонов типа [a-z] в подстановке путей даст (по известным причинам) совершенно бредовый результат.

Никому не придёт в голову экранировать все «$variable» потому что где-то выше по коду или в библиотеках используется loop/iterate/with-*.

Я не уловил суть. Однако читал о таких рекомендациях, но мне они кажутся странными. Дело в том, что $var и "$var" — это разные вещи: первый — как бы поток, который будет разбит на слова, а второй — одно слово.

Хорошо бы и в шелле иметь возможность разделять на типы данных: строка как простая последовательность символов и строка как встроенная мини-программа.

А разве нет такого? '...' — ничего не вижу (простая последовательность), $'...' — ищу управляющие символы, "..." — ищу подстановки, ну, и если ничего, то — держите меня семеро 😄

papin-aziat ★★★★★
()
Ответ на: комментарий от papin-aziat

то тогда уж до regex-ов, но ты почему-то на эту тему молчишь…

Потому что эта абстракция не протекает. Если где-то в скрипте используется регулярное выражение, то код ни выше, ни ниже никак от того не страдает. Если уж и переводить стрелки, то на исключения в «больших» языках программирования. Если ты бросаешь исключение в одном месте, то вся программа должна быть устроена с учётом возможности неожиданного прилёта исключения. А если не используешь — с учётом того, что оно всё равно может прилететь из-под какой-нибудь библиотеки. Пиши-читай внимательно!

Это какое-то заклинание древних магов борновского шелла.

Так всё башескриптование из таких заклинаний и состоит.

Дело в том, что $var и «$var» — это разные вещи: первый — как бы поток,

Везде перменная — это переменная. Если хочется поток, то его можно организовать явно. И только тут сиди да гадай echo $x тебе строку на печать выведет или диск отформатирует.

А разве нет такого? ‘…’ — ничего не вижу (простая последовательность), $‘…’ — ищу управляющие символы, «…» — ищу подстановки, ну, и если ничего, то — держите меня семеро 

Мечтается о чём-то типа:

x=$(ext-program param1 param2 param3)
y=$x

и чтобы на этапе исполнения можно было бы понять/задать тип результата. Т.е. ext-program вызывается, но результат её работы — простая строка, с которой дальше мы спокойно работать, не ожидая, что в каких-то выражениях она как-то хитро проинтерпретируется. Это бы сильно добавило скриптам надёжности.

ugoday ★★★★★
()
Ответ на: комментарий от ugoday

Потому что эта абстракция не протекает. Если где-то в скрипте используется регулярное выражение, то код ни выше, ни ниже никак от того не страдает.

Я имел в виду вынос мозга с переключением между BRE & ERE, когда выясняется, что ERE означает extended, но придётся кое-что экранировать из BRE, а потом выясняется, что BRE умеет всё то же самое, только надо экранировать кое-что из ERE, и вишенкой на торте, когда sed (который умеет только BRE) умеет в обратные ссылки… Сидишь и думаешь, и какой же из них таки достоин имени extended… Ладно, это почти шутка, а реально странно, что в результате ты должен хорошо помнить в какой функции или программе какой диалект, а если есть возможность выбирать, то помнить ключи, которые переключают диалект, и учитывая, что писать надёжные регулярные выражения само по себе непросто, то такая подстава с экранированиями выглядит как подстава уровня бог.

Так всё башескриптование из таких заклинаний и состоит.

Мне больше понравился термин «идиомы» :-)

Везде перменная — это переменная. Если хочется поток, то его можно организовать явно. И только тут сиди да гадай echo $x тебе строку на печать выведет или диск отформатирует.

Насколько я помню из Паскаля и Си, там переменные имеют строгий тип и типов этих несколько. А в баше всё проще — это всегда строка, точка. Да, можно застолбить числовые и даже более простым синтаксисом ими манипулировать, но, как я понял, в практику это не пошло (а нафига?). Массивы (списки) — просто индексированные строки, а ассоциативные (хеши) — словари из двух строк. Классно же!

Ничего гадать не надо, ты всегда получаешь поток (я могу неграмотно выжаться, помнишь?) символов и сам решаешь как его подать с одного конца на другой — в виде строки или слова. Дальше в дело вступает принимающая сторона. И пока я знаю только одну особенность, когда позиционные параметры и массивы, которые подаются целиком, можно подать тремя способами: $*/$@, ${foo[*]}/${foo[@]} — строка; "$@", "${foo[@]}" — строка, разбитая на (соответствующие) слова; "$*", "${foo[*]}" — слово.

Т.е. ext-program вызывается, но результат её работы — простая строка, с которой дальше мы спокойно работать, не ожидая, что в каких-то выражениях она как-то хитро проинтерпретируется.

Дык она и есть простая строка, всегда, гарантированно, но интерпретирует-то её принимающая программа, к ней и претензии стало быть. Если вываливаешь из ведра прямо в командную строку, то наверное лучше в отдельный контейнер, если не уверен в содержимом, или отдельными порциями в случае поз. параметров или массивов, когда надо ударить по рукам, чтоб не трогала :-)

papin-aziat ★★★★★
()
Последнее исправление: papin-aziat (всего исправлений: 1)
Ответ на: комментарий от ugoday

Кстати, у меня вопрос. Я правильно понимаю, что возможность объявлять числовые переменные (соответственно ими манипулировать без преобразований из строки в число) и битовые операции это на тот случай, чтобы оптимизировать производительность скрипта, если кто-то решит совершать в нём миллионы (миллиарды?) операций, или это может быть полезно ещё как-нибудь для простых смертных?

papin-aziat ★★★★★
()