Відповіді:
Різниця між [[ … ]]і [ … ]в основному покривається у використанні одинарного або подвійного дужок - bash . Принципово важливим [[ … ]]є спеціальний синтаксис, тоді як [команда - смішна на вигляд назва. [[ … ]]має спеціальні правила синтаксису для того, що знаходиться всередині, [ … ]не має.
З доданою зморшкою підстановки, ось як [[ $a == z* ]]оцінюється:
[[ … ]]умовна конструкція навколо умовного виразу $a == z*.==двійковий оператор, з операндами $aта z*.a.==оператора: перевірити, чи відповідає значення змінної aшаблону z*.Ось як [ $a == z* ]оцінюється:
[команда з аргументами , утворених оцінки слова $a, ==, z*, ].$aна значення змінної a.aє рядок 6 символів foo b*(отримана , наприклад a='foo b*') , і список файлів в поточному каталозі ( bar, baz, qux, zim, zum), то результат розкладання є наступним списком слів: [, foo, bar, baz, ==, zim, zum, ].[з параметрами, отриманими на попередньому кроці.
[команда скаржиться на синтаксичну помилку і повертає статус 2.Примітка. На [[ $a == z* ]]етапі 3 значення aне зазнає розщеплення слів та створення імені файлів, оскільки воно знаходиться в контексті, коли очікується одне слово (лівий аргумент умовного оператора ==). У більшості випадків, якщо одне слово має сенс на цій позиції, то змінне розширення веде себе так, як це відбувається у подвійних лапках. Однак є виняток із цього правила: у [[ abc == $a ]]випадку, якщо значення aмістить символи підстановки, aвоно співпадає з шаблоном підстановки. Наприклад, якщо значення aє a*те [[ abc == $a ]]істинно (бо підстановлювальний *виходячи з котирувального розширення $aматчів *) , тоді як [[ abc == "$a" ]]помилково (так як звичайний символ*що походить від цитованого розширення $aне відповідає bc). Всередині [[ … ]], подвійні лапки не роблять різниці, крім як на правій стороні операторів рядки відповідності ( =, ==, !=і =~).
[- псевдонім для testкоманди. У Unix версії 6 була ifкоманда, але версія 7 (1979) оснащена новою оболонкою Bourne, яка мала декілька програм програмування, включаючи конструкцію if-then-else-elif-fi, а Unix версія 7 додала testкоманду, яка виконувала більшу частину "тести", які були виконані ifкомандою у старих версіях.
[було створено псевдонім до testобох, і було вбудовано в оболонку в Unix System III (1981) . Хоча слід зауважити, що деякі варіанти Unix не мали [команди ще набагато пізніше після цього ( до початку 2000-х років на деяких BSD, де shбазується на оболонці Almquist ( testвбудований модуль завжди включався в ashджерело, але на ці BSD її спочатку було відключено)).
Зауважте, що testака [- це команда робити "тести", це завдання не виконується, тому немає ніяких причин розрізняти призначення та оператор рівності, тому оператор рівності є =. ==підтримується лише кількома останніми реалізаціями [(і є лише псевдонімом для =).
Оскільки [це не що інше, як команда, вона аналізується так само, як і будь-яка інша команда оболонкою.
Зокрема, у вашому прикладі, $aоскільки це не цитується, воно було б розділене на кілька слів за звичайними правилами розбиття слів, і кожне слово зазнало б генерації імені файлу ака-глобулінгу, що призведе до, можливо, більше слів, кожне з цих слів призведе до окремий аргумент [команди.
Так само z*було б розширено до списку імен файлів у поточному каталозі, починаючи з z.
Так, наприклад, якщо $aє b* = x, і є z1, z2, b1і b2файли в поточному каталозі, то [команда отримає 9 аргументів: [, b1, b2, =, x, ==, z1, z2і ].
[аналізує свої аргументи як умовний вираз. Ці 9 аргументів не складають дійсного умовного виразу, тому він, ймовірно, поверне помилку.
[[ ... ]]Конструкція була введена Korn оболонки , ймовірно , близько 1988 , як ksh86aв 1987 році його не було в той час як ksh88було це з самого початку.
Крім ksh (усіх реалізацій), [[...]]він також підтримується bash (починаючи з версії 2.02) та zsh, але всі три реалізації різні, і між різними версіями однієї оболонки є відмінності, хоча зміни, як правило, сумісні з зворотним ходом (помітним винятком є bash's =~оператор, який, як відомо, зламав кілька сценаріїв після певної версії, коли його поведінка змінилася). [[...]]не визначено POSIX, Unix або Linux (LSB). Він кілька разів розглядався для включення, але не включався, оскільки загальна функціональність його, що підтримується основними оболонками, вже охоплена [командою та case-in-esacконструкцією.
Вся [[ ... ]]конструкція складається з команди. Тобто він має статус виходу (що є його найважливішим активом, оскільки це результат оцінювання умовного виразу), ви можете передавати його іншій команді (хоча це не буде корисно) і взагалі використовувати її де б ви не хотіли використовувати будь-яку іншу команду (лише всередині оболонки, оскільки це - оболонка), але вона не розбирається як звичайна проста команда. Те, що знаходиться всередині, розбирається оболонкою як умовний вираз, а звичайні правила розбиття слів та створення імен файлів застосовуються по-різному.
[[ ... ]]знає про це ==з самого початку і дорівнює =1 . Помилка ksh's, хоч (і викликає плутанину і багато помилок) полягає в тому, що =і ==не є оператором рівності, а оператором зіставлення шаблонів (хоча аспект відповідності може бути відключений цитуванням, але з незрозумілими правилами, що відрізняються від оболонки до оболонки).
У вашому коді вище [[ $a == z* ]], оболонка буде розбирати ці декілька лексем у правилах, подібних до звичайних, розпізнавати їх як порівняння зі зразком, трактувати z*як шаблон, який відповідає змісту aзмінної.
Взагалі, важче стріляти в ногу, [[ ... ]]ніж це за [командою. Але кілька правил, як
-aабо -oоператор (використовувати кілька [команд і &&та || оболонки операторів)Зробіть [надійними за допомогою оболонок POSIX.
[[...]]в різних оболонках підтримують додаткових операторів, таких як оператори -ntвідповідності повторного виклику ... але список та поведінка змінюються від оболонки до оболонки та версії до версії.
Тому, якщо ви не знаєте, якою оболонкою та мінімальною версією її сценарій коли-небудь буде інтерпретований, це, ймовірно, безпечніше дотримуватися стандартної [команди.
1 Виняток: [[...]]додано до bash у версії 2.02. До 2.03тих пір, де це було б змінено, [[ x = '?' ]]повернеться правда, тоді як [[ x == '?' ]]повернеться хибним. Тобто цитування не завадило збігу шаблонів при використанні =оператора в цих версіях, але було зроблено при використанні ==.
[ '!' = foo -o a = a ]в bash, наприклад.
обидва використовуються для оцінки виразів, і [[не працюватиме з POSIX-старшою оболонкою, і [[також підтримує узгодження шаблонів і регулярний вираз. Пример спробуйте
[ $n -eq 0 -a $y -eq 0 ] && echo "Error" || echo "Ok"
[[ $n -eq 0 && $y -eq 0 ]] && echo "Error" || echo "Ok"
[[...]]підтримує регулярні виразки лише в деяких версіях деяких оболонок, як і деякі версії [підтримують узгодження регулярного виразів. Для порівняння з арифметиками, в тих оболонках, які підтримують [[, ви краще напишіть(( n == 0 && y == 0))