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

Я хочу попробовать простой скрипт

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

Но когда я запустил его, если я введу true , я увижу, что x="true" и flag="true" , но цикл не заканчивается. Что не так с этим скриптом? Как я могу правильно инвертировать логическую переменную?

  • Почему я не могу применить этот скрипт к файлам не в моем текущем каталоге?
  • Почему `rm -f! (/ Var / www / wp)` оставляет файлы в / var / www?
  • Сопоставьте первую часть имени пути и номера в конце строки
  • Скопируйте файлы, которые частично соответствуют другим файлам в другом месте
  • Запишите вывод оболочки ssh и сохраните статус выхода
  • Как я могу увидеть точную командную строку, выполняемую внутри некоторого экземпляра bash?
  • Вопрос возврата каретки
  • как я могу напечатать строку N и Mth выше или ниже соответствующей строки с помощью grep?
  • Что такое ярлык bash для перехода к предыдущему каталогу?
  • Есть ли обходной путь для удаления файла-файла Debian $ _?
  • Сигнал, который не получен с помощью скрипта, выполняется с использованием sh -c
  • массовое переименование файлов, не работающих
  • 5 Solutions collect form web for “Инвертировать логическую переменную”

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

    Хотя ! $flag ! $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 -rx if [ "$x" = "true" ]; then break; fi echo "$x: false" done 

    Хотя в 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) 

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

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

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

    Но на самом деле то, что вам нужно сделать, это заменить ваше while :

     while ! $flag 

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

     $ foo=0 $ echo $foo 0 $ ((foo ^= 1)) $ echo $foo 1 $ ((foo ^= 1)) $echo $foo 0 
     [ ${FOO:-0} == 0 ] && FOO=1 || FOO=0 

    или даже:

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

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

    Linux и Unix - лучшая ОС в мире.