Я просто задумався, у чому саме різниця між ними
[[ $STRING != foo ]]
і
[ $STRING != foo ]
є, окрім того, що останній відповідає позіксам, зустрічається в sh, а перший є розширенням, знайденим у bash.
Я просто задумався, у чому саме різниця між ними
[[ $STRING != foo ]]
і
[ $STRING != foo ]
є, окрім того, що останній відповідає позіксам, зустрічається в sh, а перший є розширенням, знайденим у bash.
Відповіді:
Існує кілька відмінностей. На мою думку, декілька найважливіших:
[
це вбудований в Баш та багатьох інших сучасних раковин. Вбудований [
подібний до test
додаткової вимоги закриття ]
. Вбудовані [
і test
імітують функціональність, /bin/[
а /bin/test
також їхні обмеження, щоб сценарії були сумісними назад. Оригінальні виконувані файли все ще існують здебільшого для відповідності POSIX та зворотної сумісності. Запуск команди type [
в Bash вказує, що [
за замовчуванням інтерпретується як вбудований. (Примітка: which [
шукає виконувані файли на PATH і еквівалентно type -p [
)[[
не настільки сумісний, він не обов'язково працюватиме з будь-якими /bin/sh
точками. Так [[
само сучасніший варіант Bash / Zsh / Ksh.[[
вбудований в оболонку і не має застарілих вимог, вам не потрібно турбуватися про розбиття слів на основі змінної IFS, щоб зіпсувати змінні, які оцінюються на рядок з пробілами. Тому вам не потрібно ставити змінну в подвійні лапки.Здебільшого, решта - це лише якийсь приємний синтаксис. Щоб побачити більше відмінностей, рекомендую це посилання на відповідь на поширені запитання: Яка різниця між тестом, [та [[? . Насправді, якщо ви серйозно ставитесь до сценарію баш, я рекомендую прочитати цілі вікі , включаючи поширені запитання, підводні камені та керівництво. Тестовий розділ із посібника також пояснює ці відмінності, і чому автор (-и) вважають [[
, що це кращий вибір, якщо вам не потрібно турбуватися про те, щоб бути портативним. Основні причини:
< >
зі зворотними косими рисами, щоб вони не оцінювалися як перенаправлення вводу, що може дійсно зіпсувати деякі речі, перезаписуючи файли. Це знову повертається до [[
побудови. Якщо [(тест) є зовнішньою програмою, оболонка повинна зробити виняток у тому, як вона оцінює, <
і >
лише при /bin/test
виклику, що насправді не має сенсу.Коротко:
[є баш Бульдін
[[] - це ключові слова
Ключові слова: Ключові слова дуже схожі на вбудовані, але головна відмінність полягає в тому, що до них застосовуються спеціальні правила розбору. Наприклад, [- це bash вбудований, тоді як [[це ключове слово bash. Вони обидва використовуються для тестування матеріалів, але оскільки [[це ключове слово, а не вбудований, він має переваги від декількох спеціальних правил аналізу, які полегшують його:
$ [ a < b ]
-bash: b: No such file or directory
$ [[ a < b ]]
Перший приклад повертає помилку, оскільки bash намагається перенаправити файл b до команди [a]. Другий приклад насправді робить те, що ви від нього очікуєте. Символ <більше не має свого особливого значення оператора перенаправлення файлів.
Джерело: http://mywiki.wooledge.org/BashGuide/CommandsAndArguments
[
команда оболонки POSIX; його не потрібно вбудовувати. ]
Це лише аргумент, який шукає ця команда, щоб синтаксис був збалансованим. Команда є синонімом, за test
винятком того, test
що не шукає закриття ]
.
Відмінності в поведінці
Деякі відмінності на Bash 4.3.11:
Розширення POSIX проти Bash:
[
є POSIX[[
є розширенням Bash¹, задокументованим за адресою: https://www.gnu.org/software/bash/manual/bash.html#Conditional-Constructsрегулярна команда проти магії
[
- це лише звичайна команда зі дивним іменем.
]
це лише аргумент, [
який запобігає використанню подальших аргументів.
Ubuntu 16.04 насправді має виконуваний файл, який /usr/bin/[
надається coreutils, але вбудована версія bash має перевагу.
Ніщо не змінюється так, як Bash розбирає команду.
Зокрема, <
це перенаправлення &&
та ||
об'єднання декількох команд, ( )
генерування підшаровок, якщо не уникнути \
, і розширення слова відбувається як завжди.
[[ X ]]
являє собою єдину конструкцію, яка робить X
магічний аналіз. <
, &&
, ||
І ()
розглядаються спеціально, і правила розбиття на слова різні.
Існують також подальші відмінності, як =
і =~
.
У Bashese: [
це вбудована команда та [[
є ключовим словом: https://askubuntu.com/questions/445749/whats-the-difference-between-shell-builtin-and-shell-keyword
<
[[ a < b ]]
: лексикографічне порівняння[ a \< b ]
: Так само, як вище. \
потрібно або інакше робить перенаправлення, як і для будь-якої іншої команди. Розширення Bash.expr a \< b > /dev/null
: POSIX еквівалент², див .: https://stackoverflow.com/questions/21294867/how-to-test-strings-for-lexicographic-less-than-or-equal-in-bash/52707989#52707989&&
і ||
[[ 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 еквівалент 5розщеплення слів і генерація імен файлів у розширеннях (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 4 , втрачає магію с''
[[ 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
подібних !
або (
.
4 в bash 3.2 і вище і за умови сумісності з bash 3.1 не ввімкнено (наприклад, з BASH_COMPAT=3.1
)
5 , хоча угруповання (тут з {...;}
командою групою замість (...)
якої буде запускати непотрібну подоболочкі) не є необхідною , як ||
і &&
оператори оболонки (на відміну від ||
і &&
[[...]]
операторів або -o
/ -a
[
операторів) мають однаковий пріоритет. Так [ a = a ] || [ a = b ] && [ a = b ]
було б рівнозначно.
printf 'ab' | grep -Eq 'ab?'
всередині if [ … ]
?
if ( printf 'ab' | grep -Eq 'a' ); then echo 'a'; fi
. []
це команда так само, як grep
. Можливо, ()
ця команда не знадобиться. Я не впевнений: я додав її через |
, залежить від того, як Bash розбирає речі. Якщо не було, |
я впевнений, що ви можете просто написати if cmd arg arg; then
.
()
ній не здається: stackoverflow.com/questions/8965509 / ...
Одинарна дужка, тобто []
оболонка POSIX, сумісна з тим, щоб укласти умовний вираз.
Подвійні дужки, тобто [[]]
розширена (або розширена) версія стандартної версії POSIX, підтримується bash та іншими оболонками (zsh, ksh).
У БАШЕЄВ, для кількісного порівняння ми використовуємо eq
, ne
, lt
і gt
, з подвійними дужками для порівняння ми можемо використовувати ==
, !=
, <,
і в >
буквальному сенсі.
[
є синонімом тестової команди. Навіть якщо він вбудований в оболонку, він створює новий процес.[[
це нова вдосконалена його версія, яка є ключовим словом, а не програмою. наприклад:
[ var1 lt var2] #works
[ var1 < var2] #error: var2 No such file or directory
[ var1 \< var2] #works with escape
[[ var1 < var2]] #works
if
заяви, дивіться mywiki.wooledge.org/BashPitfalls#if_.5Bgrep_foo_myfile.5D