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

Я нашел решение. Диск использовался в массиве RAID, поэтому мне пришлось стереть метаданные. Запустив Lubuntu с USB-накопителя, я открыл терминал и написал:

sudo dmraid -E -r /dev/sda

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

Спасибо за ваши предложения.

27
21.11.2018, 00:47
2 ответа

[ иначе test видит:

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

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

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

Чтобы получить полную информацию, посмотрите man bash , найдите test expr .

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

11
27.01.2020, 19:39

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

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


Пояснение:

Учтите следующее:

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

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

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

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

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

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

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

Bash отклонит выражение тогда и только тогда, когда 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" ]
25
27.01.2020, 19:39

Теги

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