Ошибка в проверке оболочки, когда строка является скобкой слева

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

Тогда я натолкнулся на это:

$ x='(' $ [ "$x" = '1' -a "$y" = '1' ] bash: [: `)' expected, found 1 

Попытка изолировать проблему, получив ту же ошибку:

 $ [ '(' = '1' -a '1' = '1' ] bash: [: `)' expected, found 1 

Я решил проблему следующим образом:

 [ "$x" = '1' ] && [ "$y" = '1' ] 

Еще мне нужно знать, что здесь происходит. Я верю, что вы, ребята, поможете мне в этом.

2 Solutions collect form web for “Ошибка в проверке оболочки, когда строка является скобкой слева”

Это очень непонятный краеугольный случай, когда можно было бы рассмотреть ошибку в том, как определяется тест [ встроенный; однако он соответствует поведению фактического [ двоичного кода, доступного во многих системах. Насколько я могу судить, это влияет только на определенные случаи и переменную, имеющую значение, которое соответствует [ operator like ( , ! , = , -e и т. Д.).

Позвольте мне объяснить, почему и как работать с ним в оболочках Bash и POSIX.


Объяснение:

Рассмотрим следующее:

 x="(" [ "$x" = "(" ] && echo yes || echo no 

Нет проблем; приведенное выше не дает ошибки и выводит yes . Так мы ожидаем, что работа будет работать. Вы можете изменить строку сравнения на '1' если хотите, и значение x , и она будет работать, как ожидалось.

Обратите внимание, что фактический /usr/bin/[ binary ведет себя одинаково. Если вы запускаете eg '/usr/bin/[' '(' = '(' ']' ошибки не возникает, потому что программа может обнаружить, что аргументы состоят из одной операции сравнения строк.

Ошибка возникает, когда мы и со вторым выражением. Неважно, что такое второе выражение, если оно действительно. Например,

 [ '1' = '1' ] && echo yes || echo no 

выводит yes и, очевидно, является допустимым выражением; но, если мы объединим два,

 [ "$x" = "(" -a '1' = '1' ] && echo yes || echo no 

Бэш отвергает выражение тогда и только тогда, когда x является ( или !

Если бы мы выполнили вышеуказанное, используя фактическую [ программу, т.е.

 '/usr/bin/[' "$x" = "(" -a '1' = '1' ] && echo yes || echo no 

ошибка будет понятна: поскольку оболочка выполняет подстановки переменных, /usr/bin/[ двоичный код принимает только параметры ( = ( -a 1 = 1 и завершение ] , он, по понятным причинам, не может разобрать, запускают ли открытые круглые скобки -выражение или нет, там есть и операция. Конечно, синтаксический анализ его как двух сопоставлений строк возможен, но делать это жадно, как это может вызвать проблемы при применении к соответствующим выражениям с выражением в скобках.

Проблема в том, что оболочка [ встроенная ведет себя одинаково, как если бы она расширила значение x до изучения выражения.

(Эти двусмысленности и другие, связанные с переменным расширением, были большой причиной, по которой Bash реализован, и теперь рекомендует использовать тестовые выражения [[ ... ]] .)


Обходной путь является тривиальным и часто рассматривается в сценариях с использованием старых sh оболочек. Вы добавляете «безопасный» символ, часто x , перед строками (оба значения сравниваются), чтобы гарантировать, что выражение распознается как сравнение строк:

 [ "x$x" = "x(" -a "x$y" = "x1" ] 

[ aka test видит:

  argc: 1 2 3 4 5 6 7 8 argv: ( = 1 -a 1 = 1 ] 

test принимает подвыражения в круглых скобках; поэтому он считает, что левая скобка открывает подвыражение и пытается ее разобрать; синтаксический анализатор видит = как первое в подвыражении и считает, что это неявный тест длины строки, поэтому он счастлив; затем подвыражение должно сопровождаться правой скобкой, и вместо этого парсер находит 1 вместо ) . И он жалуется.

Когда test имеет ровно три аргумента, а средний аргумент является одним из распознанных операторов, он применяет этот оператор к 1-му и 3-му аргументам без поиска подвыражений в круглых скобках.

Для полной информации смотрите man bash , найдите test expr .

Вывод: алгоритм синтаксического анализа, используемый при test является сложным. Используйте только простые выражения и используйте операторы оболочки ! , && и || объединить их.

  • Обработка ошибок в сценарии оболочки
  • Дублирование кода в скрипте оболочки
  • странное поведение команды строк
  • Как увидеть команды, выполненные в другой оболочке?
  • Как добавить данные из нескольких файлов в один файл?
  • Сортировка в обратном числовом порядке на подполе в многополевой сортировке
  • Получить список разделенных запятыми списков объектов в каталоге?
  • Сценарий строк в секунду
  • Команда Bash: возможно ли передать аргумент перед пользовательской командой (функцией) или она должна быть только после:
  • Почему я не могу назвать два псевдонима «?»?
  • Как извлечь часть имени файла в сценарий оболочки unix / linux
  • Interesting Posts

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

    Оптимизируйте find -exec {} с несколькими условиями: конкретные файлы в каталоге и определенных подкаталогах в этом каталоге

    Не уверен, какое аудиоустройство будет проходить через OVMF

    Что подразумевается под переназначением прерываний в Linux?

    Странные результаты тройного трубопровода в STDOUT & tee / dev / null> (wc -l> tmp.txt) & piping снова внедряют `cat tmp.txt`

    Как «rpm -i» пакет, только если более старая версия не существует?

    Каковы стандартные stdin и stdout дочернего процесса?

    получение имени хоста из адреса электронной почты

    Подмена текста внутри сжатых файлов

    Как проверить, перезагрузится ли мой компьютер (или завершение работы)?

    Застрял при установке grub на USB-накопитель (неизвестная файловая система / такой раздел)

    Автоматизация ввода строк в xmacro

    SSH странное поведение входа – возможно, человек в средней атаке

    Самый безопасный способ удалить USB-накопитель на Linux

    Начните прокрутку командной строки при заполнении до определенной доли

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