Відмінності в поведінці
Деякі відмінності на Bash 4.3.11:
Розширення POSIX проти Bash:
регулярна команда проти магії
[
- це лише звичайна команда зі дивним іменем.
]
це лише аргумент, [
який запобігає використанню подальших аргументів.
Ubuntu 16.04 насправді має виконуваний файл, який /usr/bin/[
надається coreutils , але вбудована версія bash має перевагу.
Ніщо не змінюється так, як Bash розбирає команду.
Зокрема, <
це перенаправлення &&
та ||
об'єднання декількох команд, ( )
генерування підшаровок, якщо не уникнути \
, і розширення слова відбувається як завжди.
[[ X ]]
являє собою єдину конструкцію, яка робить X
магічний розбір. <
, &&
, ||
І ()
розглядаються спеціально, і правила розбиття на слова різні.
Існують також подальші відмінності, як =
і =~
.
В Bashese: [
це вбудована команда і [[
є ключовим словом: /ubuntu/445749/whats-the-difference-between-shell-builtin-and-shell-keyword
<
&&
і ||
[[ a = a && b = b ]]
: вірно, логічно і
[ a = a && b = b ]
: помилка синтаксису, &&
аналізується як роздільник команд ANDcmd1 && cmd2
[ a = a -a b = b ]
: еквівалент, але застарілий POSIX³
[ a = a ] && [ b = b ]
: POSIX та надійний еквівалент
(
[[ (a = a || a = b) && a = b ]]
: помилковий
[ ( a = a ) ]
: синтаксична помилка, ()
інтерпретується як піддіаграма
[ \( a = a -o a = b \) -a a = b ]
: еквівалент, але ()
застаріло через POSIX
{ [ a = a ] || [ a = b ]; } && [ a = b ]
POSIX еквівалент⁵
розбиття слів і генерація імен файлів у розширеннях (split + glob)
x='a b'; [[ $x = 'a b' ]]
: правда, цитати не потрібні
x='a b'; [ $x = 'a b' ]
: синтаксична помилка, поширюється на [ a b = 'a b' ]
x='*'; [ $x = 'a b' ]
: помилка синтаксису, якщо в поточному каталозі є більше одного файлу.
x='a b'; [ "$x" = 'a b' ]
: POSIX еквівалент
=
[[ ab = a? ]]
: вірно, тому що це відповідає узгодженню ( * ? [
є магією). Не поширюється на файли у поточному каталозі.
[ ab = a? ]
: a?
глобус розширюється. Так може бути правдою чи помилкою залежно від файлів у поточному каталозі.
[ ab = a\? ]
: хибне, а не глобальне розширення
=
і ==
однакові в обох [
і [[
, але ==
є розширенням Bash.
case ab in (a?) echo match; esac
: POSIX еквівалент
[[ ab =~ 'ab?' ]]
: false⁴, втрачає магію с ''
[[ ab? =~ 'ab?' ]]
: правда
=~
[[ ab =~ ab? ]]
: вірно, POSIX розширений матч регулярного вираження , ?
не розширюється глобально
[ a =~ a ]
: синтаксична помилка. Немає еквіваленту баш.
printf 'ab\n' | grep -Eq 'ab?'
: POSIX-еквівалент (лише дані для одного рядка)
awk 'BEGIN{exit !(ARGV[1] ~ ARGV[2])}' ab 'ab?'
: POSIX еквівалент.
Рекомендація : завжди використовуйте []
.
Існують POSIX-еквіваленти для кожної [[ ]]
конструкції, яку я бачив.
Якщо ви використовуєте [[ ]]
:
- втрачають портативність
- змусити читача дізнатися тонкощі іншого розширення баш.
[
це лише звичайна команда зі дивним іменем, ніякої спеціальної семантики не задіяно.
¹ Натхненний еквівалентною [[...]]
конструкцією в оболонці Корна
², але не вдається для деяких значень a
або b
(як +
або index
) і робить числове порівняння, якщо a
і b
виглядає як десяткові цілі числа. expr "x$a" '<' "x$b"
працює навколо обох.
³, а також не відповідає деяким значенням a
або b
як !
або (
.
⁴ в bash 3.2 і вище і за умови сумісності з bash 3.1 не включено (як у BASH_COMPAT=3.1
)
⁵ хоча угруповання (тут з {...;}
командою групою замість (...)
якої буде працювати непотрібну подоболочкі) не є необхідним , як ||
і &&
оболонками операторів (на відміну від ||
і &&
[[...]]
операторів або -o
/ -a
[
операторів) має однаковий пріоритет. Так [ a = a ] || [ a = b ] && [ a = b ]
було б рівнозначно.
[[
з ним код добре і зрозуміло, але пам'ятаєте той день , коли ви будете порт ваших scriptworks по системі з оболонкою по замовчуванням , який не єbash
абоksh
, тощо[
- більш бридкий, громіздкий, але працює якAK-47
у будь-якій ситуації.