Инвертируйте логическую переменную

ZSH-определенной функцией являются суффиксные псевдонимы, установленные путем предоставления alias -s флаг:

alias -s ext=program

Если данное расширение имеет суффиксный псевдоним, можно выполнить файл с тем расширением непосредственно, и ZSH запустит данную программу и передаст имя файла как аргумент. Таким образом, если вышеупомянутый псевдоним в действительности, эти строки эквивалентны:

/path/to/foo.ext
program /path/to/foo.ext
28
28.07.2015, 10:06
7 ответов

В Вашем сценарии существует две ошибки. Прежде всего, Вам нужно пространство между ! и $flag, иначе оболочка ищет названную команду !$flag. Вторая ошибка - это -eq для целочисленных сравнений, но Вы используете его на строке. В зависимости от Вашей оболочки любой Вы будете видеть сообщение об ошибке, и цикл продолжится навсегда потому что условие [ "$x" -eq "true" ] не может быть верным, или каждое значение нецелого числа будут рассматривать как 0, и цикл выйдет при вводе какой-либо строки (включая false) кроме числа, отличающегося от 0.

В то время как ! $flag корректно, это - плохая идея рассматривать строку как команду. Это работало бы, но это будет очень чувствительно к изменениям в Вашем сценарии, так как необходимо было бы удостовериться это $flag никогда не может быть совсем не true или false. Было бы лучше использовать сравнение строк здесь, как в тесте ниже.

flag=false
while [ "$flag" != "true" ]
do
   read x
   if [ "$x" = "true" ]
   then
     flag=true
   fi
   echo "${x} : ${flag}"
done

Существует, вероятно, лучший способ выразить логику, которая Вы после. Например, Вы могли сделать бесконечный цикл и повредить его при обнаружении условия завершения.

while true; do
  read -r x
  if [ "$x" = "true" ]; then break; fi
  echo "$x: false"
done
22
27.01.2020, 19:39

Это работает на меня:

flag=false
while [[ "$flag" == "false" ]]
do
   read x
   if [[ "$x" == "true" ]]
   then
     flag=true
   fi
   echo "${x} : ${flag}"
done

Но на самом деле то, что необходимо сделать, заменить Ваш while с:

while ! $flag
2
27.01.2020, 19:39

Хотя в Bash нет булевых переменных, эмулировать их с помощью арифметической оценки очень просто.

flag= # False
flag=0 # False
flag=1 # True (actually any integer number != 0 will do, but see remark below about toggling)
flag="some string" # Maybe False (make sure that the string isn't interpreted as a number)

if ((flag)) # Test for True
then
  : # do something
fi

if ! ((flag)) # Test for False
then
  : # do something
fi

flag=$((1-flag)) # Toggle flag (only works when flag is either empty or unset, 0, 1, or a string which doesn't represent a number)

Это также работает в кш. Я не удивлюсь, если она работает во всех POSIX-совместимых оболочках, но не проверил стандарт.

11
27.01.2020, 19:39
[ ${FOO:-0} == 0 ] && FOO=1 || FOO=0

или даже:

[ ${FOO:-false} == false ] && FOO=true || FOO=false

должен выполнить работу

-1
27.01.2020, 19:39

Если вы можете быть абсолютно уверены, что переменная будет содержать либо 0 или 1, вы можете использовать побитовый оператор XOR-equal для переключения между двумя значениями:

$ foo=0
$ echo $foo
0
$ ((foo ^= 1))
$ echo $foo
1
$ ((foo ^= 1))
$echo $foo
0
12
27.01.2020, 19:39

untilявляется сокращением отwhile !until, в отличие от !это Борн ), так что вы можете сделать:

flag=false
until "$flag"
do
   IFS= read -r x
   if [ "$x" = true ]
   then
     flag=true
   fi
   printf '%s\n' "$x : $flag"
done

Что должно совпадать с:

flag=false
while ! "$flag"
do
   IFS= read -r x
   if [ "$x" = true ]
   then
     flag=true
   fi
   printf '%s\n' "$x : $flag"
done

Вы также можете написать это как:

until
   IFS= read -r x
   printf '%s\n' "$x"
   [ "$x" = true ]
do
   continue
done

Часть между until/ whileи doне обязательно должна быть одной командой.

!— это ключевое слово в синтаксисе оболочки POSIX. Он должен быть разделен, токен отделен от того, что следует за ним, и должен быть первым токеном, который предшествует конвейеру.(! foo | barотменяет конвейер, а foo | ! barнедействителен, хотя некоторые оболочки принимают его как расширение ).

!trueинтерпретируется как команда !true, которая вряд ли существует. ! trueдолжно работать. !(true)должен работать в оболочках, совместимых с POSIX -, поскольку !ограничен, поскольку за ним следует токен (, но на практике он не работает в ksh/bash -O extglob, где он конфликтует с !(pattern)расширенный оператор glob nor zsh (, за исключением эмуляции схемы ), где он конфликтует с glob(qualifiers)с bareglobqualи glob(group)без.

1
27.01.2020, 19:39

В оболочке нет понятия логической переменной.
Переменные оболочки могут быть толькоtext(строкой ), и в некоторых случаях этот текст может интерпретироваться как целое число (1, 0xa, 010и т. д. ).

Таким образом, a flag=trueне означает истинности или ложности оболочки вообще.

Строка

Что можно сделать, так это либо сравнить строки [ "$flag" == "true" ], либо использовать содержимое переменной в какой-либо команде и проверить ее последствия , например выполнить true(, потому что есть исполняемый файл с именем trueи один вызываетсяfalse)как команда и проверяется, равен ли код выхода этой команды нулю (успешно ).

$flag; if [ "$?" -eq 0 ]; then... fi

Или короче:

if "$flag"; then... fi

Если содержимое переменной используется в качестве команды, !можно использовать для отмены статуса выхода команды, если между обоими(! cmd)есть пробел, как в:

if ! "$flag"; then... fi

Скрипт должен измениться на:

flag=false
while ! "$flag" 
do
   read x
   if [ "$x" == "true" ]
   then
     flag=true
   fi
   echo "${x} : ${flag}"
done

Целое число

Использовать числовые значения и арифметические расширения .

В этом случае код выхода $((0))1, а код выхода $((1))0.
В bash, ksh и zsh арифметика может выполняться внутри заметки((..))(о том, что начальный $отсутствует ).

flag=0; if ((flag)); then... fi

Портативная версия этого кода более запутана:

flag=0; if [ "$((flag))" -eq 0 ]; then... fi      # test for a number
flag=0; if [ "$((flag))"  == 0 ]; then... fi      # test for the string "0"

В bash/ksh/zsh можно сделать:

flag=0    
while ((!flag)) 
do
   read x
   [ "$x" == "true" ] && flag=1
   echo "${x} : ${flag}"
done

В качестве альтернативы

Вы можете «Инвертировать логическую переменную» (, если она содержит числовое значение )как:

((flag=!flag))

Это изменит значение flagлибо на 0, либо на 1.


Примечание.:Пожалуйста, проверьте наличие ошибок в https://www.shellcheck.net/, прежде чем публиковать свой код в виде вопроса, много раз этого достаточно, чтобы найти проблему.

0
27.01.2020, 19:39

Теги

Похожие вопросы