Навіщо використовувати подвійні лапки в [[]] тесті?


23

Скажімо, у нас є два цілих числа в bash-скрипті:

value1=5
value2=3

Тоді навіщо нам використовувати подвійні лапки у разі тесту? Наприклад:

if [[ "$value1" -eq "$value2" ]]

Чому б просто не скористатися наступним?

if [[ $value1 -eq $value2 ]]

Для мене подвійні цитати не мають жодного сенсу.


5
Цитування в оболонці мало спільного з рядками (як у типах даних.) Дійсно про те, щоб оболонка не
могла

13
Хоча, як зазначив тердон, не потрібно занадто цитувати змінні в цій конкретній конструкції (і, звичайно, з однозначними значеннями в будь-якому місці), я б хотів дати пораду завжди цитувати ваші зміни. Ви дійсно знаєте, в яких контекстах ви можете залишати змінні без котирування? Причина цитувати взагалі, навіть якщо це не потрібно з 5і 3- це ремонтопридатність. Значення можуть змінитися пізніше, і виникаючі помилки можуть бути не очевидними.
Пітер - Відновити Моніку

2
@sudodus Я не думаю, що це правда [[ ]], лише для [ ].
Бенджамін В.

1
Ви маєте рацію, @BenjaminW. Розщеплення слів - не єдиний випадок, чому корисно використовувати подвійні лапки для змінних. Існує також випадок, коли змінна порожня. Це зробить заяву в [] невдалою (наприклад, [2 -eq] з помилкою, але [[]] не є вразливою (як у випадку з розщепленням слів). "
sudodus

2
@marcelm, Bash, ksh і Zsh мають цілі змінні, і всередині [[ ]]них також примушують операнди -eqдо цілих чисел.
ilkkachu

Відповіді:


7

Розбиття слів.

Цей приклад дуже малоймовірний, але можливий , тому, якщо ви хочете кодувати оборонно, покрийте свої доріжки лапками:

$ set -x
$ value1=5
+ value1=5
$ value2=3
+ value2=3
$ [ $value1 -eq $value2 ]
+ '[' 5 -eq 3 ']'

Гаразд, все добре поки що. Закинемо гайковий ключ у шестерні:

$ IFS=456
+ IFS=456
$ [ $value1 -eq $value2 ]
+ '[' '' -eq 3 ']'
bash: [: : integer expression expected

На жаль

$ [ "$value1" -eq "$value2" ]
+ '[' 5 -eq 3 ']'

А-а-а.


2
Але ОП використовує подвійні дужки, тому розбиття слів не відбувається.
user000001

5
Так, це насправді не стосується [[ ]]конструкції Баша .
тердон

1
Так? [ $value1 -eq $value2 ]з порожнім value1було б '[' -eq 3 ']'без ''лівого боку.
Чарльз Даффі

Я теж був здивований, але є докази.
glenn jackman

1
Ця відповідь безпосередньо не стосується питання. Я здивований, що це було прийнято. Налаштування як вікі спільноти.
Гленн Джекман

35

Тут вам фактично не потрібні цитати. Це один з небагатьох випадків, коли безпечно використовувати змінну без котирування. Ви можете підтвердити це за допомогою set -x:

$ var1=""
$ var2="3"
$ set -x
$ if [[ $var1 -eq $var2 ]]; then echo "match!"; else echo "no match!"; fi
+ [[ '' -eq 3 ]]
+ echo 'no match!'
no match!
$ if [[ "$var1" -eq "$var2" ]]; then echo "match!"; else echo "no match!"; fi
+ [[ '' -eq 3 ]]
+ echo 'no match!'
no match!

Як ви бачите вище, версії тесту, що цитуються і цитуються, вирішуються точно так само, як і Bash. Те саме має стосуватися zshі будь-якої іншої оболонки, яка підтримує [[ ]]оператора.

Зауважте, що це не так у випадку з більш портативними [ ]:

$ if [ $var1 -eq $var2 ]; then echo "match!"; else echo "no match!"; fi
+ '[' -eq 3 ']'
sh: [: -eq: unary operator expected
+ echo 'no match!'
no match!

[ ]Конструкція, в відміну від[[ ]] одного, вимагає лапок.


Деякі корисні посилання, щоб дізнатися більше про те, коли і навіщо потрібно цитувати:


У цьому випадку з цілими змінними було б краще оголосити їх такими. declare -i var1=є 0при оцінці.
Фредді

4
Зверніть увагу, що -eqце арифметичне порівняння, тому ви можете навіть залишити $аут (і [[ .. ]]) та написати [[ a -eq b ]]. При порівнянні рядків вам потрібно $, звичайно, так[[ $a = $b ]]
ilkkachu

2
@ user000001 хороший момент. Хоча, звичайно, дуже можливо, що ви хочете, щоб вони розширилися. Наприклад, я б очікувати , що це буде матч: var1="afoob"; var2="a*b"; [[ $var1 = $var2 ]] && echo match. Якщо ви хочете використовувати глобусні символи, не виконуючи їх роль як глобус у глобальному контексті (наприклад, the [[ ]]), тоді вам потрібно цитувати, так.
тердон

3
@ilkkachu, це мене дивує. Я думав, що "голі" змінні будуть розглянуті лише в межах індексів масиву або ((...))або $((...). Здається, це працює, але (старий бурмотливий чоловік, включіть) мені це не подобається.
glenn jackman

1
@glennjackman, ну, вибачте за те, що вам це скажу, але так, операнди -eqта друзі всередині [[ ]]є також арифметичними контекстами. :) (Пов'язано: Автоматичне розширення змінної всередині команди bash [[]] )
ilkkachu

17

Незважаючи на те, що подвійні лапки не потрібні, причини їх використання:

  • Гарна практика / звичка: у цьому випадку вони не потрібні, але загалом подвійні лапки повинні уникати навмисного розбиття слів.
  • Тому value1і value2мінливі, і ви можете не знати , що вони містять. В іншому випадку ви можете також запитати: "Навіщо турбуватися зі змінними, а не перевіряти if [[ 5 -eq 3 ]]? Або брати далі, навіщо взагалі турбуватися з тим, ifколи ви вже знаєте, що 5 не дорівнює 3? Часто краще бути оборонним." це розділення слів не відбудеться [[, але випадки, коли розбиття слів не відбувається, є рідкісними. Знову див. перший пункт.)

1

Не має прямого відношення до вашого питання, але я використовую

if (($ value1 == $ value2)); потім

коли я порівнюю цифри, але там також вам не доведеться використовувати лапки.


2
if (( value1 == value2 )); then. У арифметичних контекстах вам це навіть не потрібно $. Однак, схоже, це питання стосується змінних, які використовуються в [[ ... ]]тестах.
Kusalananda

1
Я знаю. Але я, відверто кажучи, не використовую цю функцію, оскільки хочу, щоб мої імена змінних були послідовними, і, таким чином, весь час використовувати $ як префікс.
framp

1

Ти абсолютно правий!

Цитування в подвійних квадратних дужках взагалі не має сенсу, принаймні в цьому випадку.

Але оскільки я використовую подвійні лапки щодня - особливо для виразів з одноквадратними дужками, передачі аргументів функціям та сценаріям, а також присвоєння змінних іноді (що зовсім марно для простих декарацій) - я думаю, що деякі люди, принаймні, я, писати подвійні лапки навколо змінних розширень інстинктивно .

Подвійне цитування може дати вам відчуття економії. Це як повернутися додому, де є подвійні цитати. - Д. Куммер

Користь робити подвійні цитати, як наслідок, і зрозуміло - але лише так, як це має сенс - полягає в тому, що колеги, які не знайомі з баш, можуть навчитися писати більш стабільні сценарії . Він також наголошує на тому, що мистецтво обробки даних за допомогою bash - це більше про відокремлення потоків даних (включаючи змінні) на роздільники полів та передачу їх через фільтри . Як тільки у вас відокремлюються фрагменти даних від потоку, тримайте їх разом із подвійними лапками!

Ще однією перевагою може стати краща читабельність скриптів bash з подвійними цитованими рядками в редакторі виділення коду .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.