Не могли бы вы объяснить синтаксис математики в bash оболочке? - PullRequest
4 голосов
/ 15 января 2020
for i in {1..99}
do
  if ([ $((i % 2)) -eq 1 ])
  then
      echo $i
  fi
done

Я изучаю bash и пытаюсь лучше понять строку 3. Почему $((i % 2)) необходимо заключить в круглые скобки и почему я не могу поставить символ $ внутри рядом с i вроде:

([ (($i % 2)) -eq 1 ])

или

([ ($(i % 2)) -eq 1 ])

?

Ответы [ 4 ]

5 голосов
/ 15 января 2020

Все внутри $((...)) рассматривается как арифметическое c выражение. Вы можете использовать расширение параметра внутри выражения arithmeti c, но пустая строка интерпретируется как переменная, значение которой (целое) используется. Вы можете написать

if [ $(( i % 2 )) -eq 1 ]

, чтобы проверить, является ли i нечетным. Вы также можете проверить равенство внутри выражения, так как $(( x == y )) оценивается как 1, если x == y и 0 в противном случае, но вам все равно придется сравнить это значение с чем-то.

In bash, вы можете использовать арифметическую c команду , которая имеет статус выхода 0, если результирующее значение не равно нулю, и 1 в противном случае. Это позволяет вам написать

if (( i % 2 == 1 )); then
4 голосов
/ 15 января 2020

$(( expression )) - это синтаксис для вычисления арифметического выражения c и замены этого синтаксиса на результат этого выражения. Это задокументировано в Bash Руководстве здесь ;

Синтаксис арифметических c выражений описан здесь . Размещение $ перед именами переменных не является обязательным, поэтому вы также можете записать его как $(($i % 2)).

Вы должны заключить его в две скобки, потому что $(...) уже имеет значение, оно используется для Подстановка команды : $(some command) выполняет some command и затем заменяется выводом команды.

Вам не нужны круглые скобки вокруг [ ... ]. Обычный способ написать оператор if:

if [ $((i % 2)) -eq 1 ]

. Вы также можете записать его как

if (( i % 2 == 1 ))

(( expression )), вычисляя выражение арифметического c, и затем устанавливая его состояние выхода в зависимости от того, является ли результат нулевым или ненулевым.

0 голосов
/ 16 января 2020

Вы также можете использовать expr:

for i in {1..99}
do
  num=`expr i % 2`
  if (( num == 1 ))
  then
      echo $i
  fi
done
0 голосов
/ 16 января 2020

Поскольку вы указываете bash, самое простое -

for i in {1..99}
do  if ((i % 2)) 
    then echo $i
    fi
done

, ((i % 2)) вернет i mod 2, который всегда будет равен нулю или единице. Эта конкретная конструкция ведет себя как логический тип C, так что ноль равен false, а все остальное верно (противоположное поведение от [[ ... ]], в котором return код нуля означает true / ok).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...