LINUX.ORG.RU

Bash: зачем в условии пишут символ перед переменной: [[ «x$A» = «x$B» ]] ?

 


2

2

Всем привет

Помню встречал, что в условиях пишут символ перед переменной, например [[ «x$A» = «x$B» ]] . Помню, что даже вроде это нужно на случай, если одна из переменных окажется пустой. Но не могу воспроизвести кейс, когда это хоть как-то меняло бы поведение проверки условия.

Так зачем пишут символ перед переменной в условии?

★★★★★

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

anonymous
()
Ответ на: комментарий от anonymous

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

Пример кода, который без символа впереди работает некорректно?
Я не смог воспроизвести.

Kroz ★★★★★
() автор топика

[[ — башизм.

$ a= b=1
$ [ $a = $b ]
-sh: [: =: unary operator expected
$ [[ $a = $b ]]
$

anonymous
()
Ответ на: комментарий от Kroz

На самом деле это пережиток очень давних времён, относится только к синтаксису древних реализаций комады test (или «[»), и главная опасность - не пустая переменная, а ключевое слово (например, "-n" или «=») в качестве значения.

ABW ★★★★★
()

http://www.tldp.org/LDP/abs/html/comparison-ops.html

-n

string is not null.

Caution

The -n test requires that the string be quoted within the test brackets. Using an unquoted string with ! -z, or even just the unquoted string alone within test brackets (see Example 7-6) normally works, however, this is an unsafe practice. Always quote a tested string. [1]

Notes [1]

As S.C. points out, in a compound test, even quoting the string variable might not suffice. [ -n «$string» -o «$a» = «$b» ] may cause an error with some versions of Bash if $string is empty. The safe way is to append an extra character to possibly empty variables, [ «x$string» != x -o «x$a» = «x$b» ] (the «x's» cancel out).

aedeph_ ★★
()
Последнее исправление: aedeph_ (всего исправлений: 1)

например [[ «x$A» = «x$B» ]]

тут по привычке или «чтоб наверняка», видимо

т.к. ЕМНИП [[ решает проблему, и x в кавычки не берут в случае [

$ A=1; B= ; [[ x$A = x$B ]] 
$ A=1; B= ; [ x$A = x$B ] 
$ A=1; B= ; [ $A = $B ] 
bash: [: 1: ожидается унарный оператор
$ A=1; B= ; [[ $A = $B ]]
$

anTaRes ★★★★
()

Это верно для sh, так как [ является синонимом команды test и имеет ряд недостатков.

Для bash, в котором [[ является конструкцией языка, не нужны ни дополнительные символы, ни кавычки переменным внутри выражения.

lexazloy
()

например [[ «x$A» = «x$B» ]]

В таком виде не видел ни разу. С [ ещё можно встретить, но очень-очень редко.

redgremlin ★★★★★
()
Ответ на: комментарий от Kroz

Пример кода, который без символа впереди работает некорректно?
Я не смог воспроизвести.

#!/bin/sh

a='-n'
b=''
[ $a = $b ]

a=''
b=''
[ $a = $b ]

Оба варианта выплюнут ошибку.

Это при условии, что у тебя /bin/sh не является симлинком на полноценный шелл типа bash.

Буквально пару дней назад столкнулся с проблемой, когда одна из переменных пустая. Башу на это пофиг, но башизмы — зло.

r3lgar ★★★★★
()
Ответ на: комментарий от Kroz

но башизмы — зло.

Почему?

Потому, что баш является дефолтом лишь в Linux, а Linux — это далеко не единственная UNIX-like в природе, и никто в здравом уме не станет ставить баш: где-то он просто не нужен из-за полутора скриптов, где-то его поставить не так просто. Так что если есть возможность, то не нужно городить башизмов. Хотя бы чтобы любой нуждающийся в твоём скрипте мог с меньшими трудозатратами перенести его под свой шелл (иначе будет дешевле просто написать с нуля).

r3lgar ★★★★★
()
Ответ на: комментарий от lexazloy

доказать, что [ «x$A» = «x$B» ] верно для sh, что «x» обязателен для какой-нибудь POSIX shell совместимой оболочки

anonymous
()
Ответ на: комментарий от former_anonymous

Давно не встречал ситуацию когда /bin/sh это ссылка на /bin/bash. В каком дистрибутиве такое?

Opensuse Leap 42.1

Elyas ★★★★★
()
Ответ на: комментарий от former_anonymous

Давно не встречал ситуацию когда /bin/sh это ссылка на /bin/bash. В каком дистрибутиве такое?

В генте, например:

 # > equery b /bin/sh
 * Searching for /bin/sh ...
app-shells/bash-4.4_p5-r1 (/bin/bash)
 # > lss /bin/sh
lrwxrwxrwx 1 root root 4 Dec  7 19:51 /bin/sh -> bash*
 # > 
Хоть оно и старается вести себя как sh, оно не sh.

r3lgar ★★★★★
()
Ответ на: комментарий от lexazloy

кавычки у переменной справа все-таки не помешают

anonymous
()
Ответ на: комментарий от former_anonymous

Например арч и, рискну предположить, вообще большая часть НЕ deb-based.

anonymous
()

Костыли не нужны, просто надо взять за привычку кавычить все значения переменных.

ArcFi
()
Ответ на: комментарий от former_anonymous

Давно не встречал ситуацию когда /bin/sh это ссылка на /bin/bash. В каком дистрибутиве такое?

А я вот давно не встречал где это не ссылка.
В RedHat/CentOS и Gentoo - ссылка.

Kroz ★★★★★
() автор топика
Ответ на: комментарий от Kroz

вроде в каких-то *BSD не принято, в остальных вроде как наоборот

anTaRes ★★★★
()
Ответ на: комментарий от evilface

[ — /bin/[

это где так?

а значения ей (значения переменных, сравнение, скобка в конце) передаются аргументами командной строки.

и?

anonymous
()
Ответ на: комментарий от anonymous

это где так?

Это в общем случае. /usr/bin/[ то есть.

и?

$ /usr/bin/[1 -eq 2]
sh: 1: /usr/bin/[1: not found


А у шелл-билтинов совместимость.

evilface ★★
()
Ответ на: комментарий от r3lgar

Свежие продукты не нужны. Купить их можно только в магазине, а не все пользуются магазинами, некоторые пользуются помойкой, где найти свежие продукты проблематично. Поэтому готовить надо только из протухших продуктов, чтобы любой бомж Вася смог бы повторить этот рецепт, иначе ему придётся придумывать себе рецепт с нуля.

redgremlin ★★★★★
()
Последнее исправление: redgremlin (всего исправлений: 1)
Ответ на: комментарий от evilface

так и не понял, что вы хотите сказать (и как это относится к сабжу), даже если добавить пробелы и экранирование

anonymous
()
Ответ на: комментарий от redgremlin

не совсем верная аналогия

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

зло потому - что мало кто учитывает эти нюансы при написании скриптов
а потом они методом копи-пасты заполоняют весь интернет
и лет нцать спустя ты находишь решение какой-то редкой проблемы, и там подобный скрипт, и он не работает
например

далеко ходить не нужно, вон прям тут [[ «x$A» = «x$B» ]], и уже никто не помнит почему именно так ;)

anTaRes ★★★★
()
Ответ на: комментарий от anTaRes

но если ты захочешь с кем-то поделиться скриптом

Я уже вряд ли захочу поделиться с кем-то скриптом на баше, я как-то осознал, что на перле большинство моих хотелок делаются проще и быстрее (в некоторых случаях с perl6 это в разы проще и быстрее) и сейчас баш ни для чего, сложнее однострочников (да и то, это получается скорее coreutils сотоварищи, чем баш), не применяю, перл есть один фиг везде.

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

У какой половины? Не-линукс на 99% состоит из нишевых решений, где требуются весьма специфичные знания, слабо пересекающиеся с daily-use шелл-скриптингом. Будем честны — фактически это касается только тех, кто юзает *BSD там, где вполне можно обойтись линуксом, но не хочется, и по похожим религиозным причинам не хочет ставить/использовать баш. Но они сами выбрали путь страданий.

redgremlin ★★★★★
()
Ответ на: комментарий от redgremlin

Будешь молоть подобную чушь тогда, когда как минимум *BSD на серверах переведутся.

r3lgar ★★★★★
()
Ответ на: комментарий от anTaRes

Да чего ты объясняешь этому школьнику? Он кроме линуксов ничего и не видел, и считает наличие bash — правилом.

r3lgar ★★★★★
()
Ответ на: комментарий от redgremlin

сотоварищи

Правильно — «со товарищи». Раньше творительный падеж был неотличим от именительного, и «со товорищи» означало «с товарищами». А «сотоварищи» — это множественное число слова «сотоварищ», т.е. бред в этом контексте.

anonymous
()
Ответ на: комментарий от former_anonymous

Давно не встречал ситуацию когда /bin/sh это ссылка на /bin/bash. В каком дистрибутиве такое?

А какие ты встречаешь? Похоже, что один и тот же, с разными нескучными обоями, если:

Генту с Арч не нужны, а про RH интересно

пысы: В Слаке ещё.

ashot ★★★★
()
Ответ на: комментарий от Kroz

Хотя бы чтобы любой нуждающийся в твоём скрипте мог с меньшими трудозатратами перенести его под свой шелл (иначе будет дешевле просто написать с нуля).

А если нуждающийся так и не появится?

Если ты рисуешь скрипт для своих целей, начинай со строчки «#!/bin/bash» и не парься.

Ещё неизвестно захочешь ли ты делиться своим скриптом с кем-либо, неизвестно нужен ли этот скрипт кому-либо кроме тебя, так стоит ли заморачиваться с потенциальной совместимостью с абстрактным сферическим шеллом в вакууме, окаменевшим, как говно мамонта? Всё равно всех граблей не предусмотришь, так как шеллов (включая разные версии одного и того же шелла) — как звёзд на небе, и у каждого свои заморочки.

Проблемы портабельности будешь решать по мере их появления. Можешь ознакомиться с неполным списком проблем здесь: Portable Shell Programming и подумать — а стоит ли овчинка выделки?

debugger ★★★★★
()
Последнее исправление: debugger (всего исправлений: 1)
Ответ на: комментарий от redgremlin

Я уже вряд ли захочу поделиться с кем-то скриптом на баше, я как-то осознал, что на перле большинство моих хотелок делаются проще и быстрее…

В перле те же самые проблемы, только вид сбоку: Захочешь пользоваться современными фишками, что-нить типа =~ /x/y/r или $a // $b — понабегут и станут говорить что это зло, так как на православном перл 5.6 это не работает. Попользуешь модуль из цпана — скажут что зло так как не будет работать на системах с голым перлом, и надо использовать только модули, поставляемые с перлом, причём тем самым, 5.6.

debugger ★★★★★
()
Ответ на: комментарий от anTaRes

но если ты захочешь с кем-то поделиться скриптом - то у половины народу он просто не будет работать

С чего бы, если первой строкой #!/usr/bin/env bash стоит? Так же и будет работать.

d_a ★★★★★
()
Ответ на: комментарий от debugger

поэтому свои скрипты я пишу на zsh.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.