Може хтось, будь-ласка, пояснить різницю між сценаріями -eqта ==в баш?
Чи є різниця між наступним?
[ $a -eq $b ]
і [ $a == $b ]
Чи просто ==він використовується лише тоді, коли змінні містять числа?
Може хтось, будь-ласка, пояснить різницю між сценаріями -eqта ==в баш?
Чи є різниця між наступним?
[ $a -eq $b ]
і [ $a == $b ]
Чи просто ==він використовується лише тоді, коли змінні містять числа?
Відповіді:
І навпаки: =і ==для порівняння рядків, -eqце для числових. -eqзнаходиться в тій же сім'ї , як -lt, -le, -gt, -geі -ne, якщо це допоможе вам згадати , що є що.
==це, до речі, баш-ізм. Краще використовувати POSIX =. У bash два рівноцінні, а в звичайному sh =- єдиний, що гарантовано працює.
$ a=foo
$ [ "$a" = foo ]; echo "$?" # POSIX sh
0
$ [ "$a" == foo ]; echo "$?" # bash specific
0
$ [ "$a" -eq foo ]; echo "$?" # wrong
-bash: [: foo: integer expression expected
2
(Бічна примітка: Цитуйте ці змінні розширення! Не виключайте подвійних лапок вище.)
Якщо ви пишете #!/bin/bashсценарій, то рекомендую використовувати [[замість цього . У подвоєній формі є більше можливостей, природніший синтаксис та менша кількість готчей, які будуть вас обтяжувати. Подвійні лапки більше не потрібні $aдля одного:
$ [[ $a == foo ]]; echo "$?" # bash specific
0
Дивитися також:
[[ $var = $pattern ]], якщо ви хочете , що б в іншому випадку можна інтерпретувати як шаблон fnmatch замість цього слід інтерпретувати як символьний рядок. Рядок fooне має нелітеральної інтерпретації, що робить залишення цитат абсолютно безпечним; це стосується лише того, що ОП хотіла б відповідати, скажімо, foo*(зірочкою як буквальною, не маючи на увазі нічого, що може з’явитися після рядка foo), то котирування або пробіг знадобиться.
[[були башизмом (вказуючи на те, що це була єдина причина, по якій ви не давали відповіді +1).
[ ... ]і подвійний знак рівності ==. : - /
Це залежить від конструкції тесту навколо оператора. Ваші варіанти - це подвійні дужки, подвійні дужки, одинарні дужки або тест
Якщо ви використовуєте ((...)) , ви тестуєте арифметичний власний капітал з, ==як у C:
$ (( 1==1 )); echo $?
0
$ (( 1==2 )); echo $?
1
(Примітка: 0означає trueв сенсі Unix і не нуль - це невдалий тест)
Використання -eqвсередині подвійних дужок є синтаксичною помилкою.
Якщо ви використовуєте [...] (або одиночну дужку) або [[...]] (або подвійну дужку), або testви можете використовувати один із -eq, -ne, -lt, -le, -gt або -ге як арифметичне порівняння .
$ [ 1 -eq 1 ]; echo $?
0
$ [ 1 -eq 2 ]; echo $?
1
$ test 1 -eq 1; echo $?
0
==Усередині одинарні або подвійні дужки (або testкоманди) є одним з операторів порівняння рядків :
$ [[ "abc" == "abc" ]]; echo $?
0
$ [[ "abc" == "ABC" ]]; echo $?
1
Як струнний оператор, =еквівалентний ==і відзначає пробіл навколо =або ==його необхідний.
Хоча ти можеш це зробити [[ 1 == 1 ]]або [[ $(( 1+1 )) == 2 ]]це тестування рівності рядків - не арифметична рівність.
Таким чином, -eqотриманий результат, ймовірно, очікується, що ціле значення рівня 1+1дорівнює, 2хоча RH - це рядок і має проміжний простір:
$ [[ $(( 1+1 )) -eq "2 " ]]; echo $?
0
Хоча порівняння рядків одного і того ж збирає простір, і порівняння рядків не вдається:
$ [[ $(( 1+1 )) == "2 " ]]; echo $?
1
І помилкове порівняння рядків може дати повну неправильну відповідь. '10' лексикографічно менше, ніж '2', тому порівняння рядків повертає trueабо 0. Стільки помилок укусує ця помилка:
$ [[ 10 < 2 ]]; echo $?
0
проти правильного тесту на 10, арифметично менше 2:
$ [[ 10 -lt 2 ]]; echo $?
1
У коментарях виникає питання про технічну причину використання цілого числа -eqна рядках повертає True для рядків, які не є однаковими:
$ [[ "yes" -eq "no" ]]; echo $?
0
Причина в тому, що Баш нетипізований . -eqПризводить до того , рядках повинні інтерпретуватися як цілі числа , якщо це можливо , включаючи базову перетворення:
$ [[ "0x10" -eq 16 ]]; echo $?
0
$ [[ "010" -eq 8 ]]; echo $?
0
$ [[ "100" -eq 100 ]]; echo $?
0
І 0якщо Баш вважає, що це просто рядок:
$ [[ "yes" -eq 0 ]]; echo $?
0
$ [[ "yes" -eq 1 ]]; echo $?
1
Так що [[ "yes" -eq "no" ]]еквівалентно[[ 0 -eq 0 ]]
Останнє зауваження: Багато розширень Bash для тестових конструкцій не є POSIX, а тому не спрацюють з іншими оболонками. Інші снаряди зазвичай не підтримують [[...]]та ((...))або== .
[[ "yes" -eq "no" ]]повернення True. Як bash примушує ці рядки до цілих значень, які можна порівняти? ;-)
[[ "yes" -eq "no" ]]еквівалентні [[ "yes" -eq 0 ]] або [[ "yes" -eq "any_noninteger_string" ]]- All True. Ці -eqсили цілого порівняння. "yes"Інтерпретується як ціле число 0; порівняння - Істинне, якщо інше ціле число є 0або результатом рядка є 0.
==у зразках коду (лише перенесення даних) та лише згадування (переносний, стандартизований) =під ним.
==є псевдонімом, характерним для bash, =і він виконує рядкове (лексичне) порівняння замість числового порівняння. eqяк числове порівняння, звичайно.
Нарешті, я зазвичай вважаю за краще використовувати форму if [ "$a" == "$b" ]
==тут є поганою формою, оскільки лише =визначено POSIX.
==тоді поставте їх між [[і ]]. (І переконайтеся, що перший рядок вашого сценарію вказаний для використання /bin/bash.)
Хлопці: Кілька відповідей показують небезпечні приклади. У прикладі ОП [ $a == $b ]спеціально використовується підстановка змінної без котирування (станом на жовтень 17 редагування). Бо [...]це безпечно для рівних рядків.
Але якщо ви збираєтесь перелічити подібні альтернативи [[...]], ви також повинні повідомити, що праворуч треба цитувати. Якщо не цитується, це відповідність шаблону! (З сторінки bash man: "Будь-яка частина шаблону може бути цитована, щоб змусити його відповідати як рядок.").
Тут у bash, два твердження, що дають "так", відповідають зразкам, інші три - рівними рядками:
$ rht="A*"
$ lft="AB"
$ [ $lft = $rht ] && echo yes
$ [ $lft == $rht ] && echo yes
$ [[ $lft = $rht ]] && echo yes
yes
$ [[ $lft == $rht ]] && echo yes
yes
$ [[ $lft == "$rht" ]] && echo yes
$
[ "$lht" = "$rht" ] цитати були надійними навіть для рівності. Якщо у вас створений файл touch 'Afoo -o AB', [ $lft = $rht ]він поверне true, навіть якщо ім'я цього файлу зовсім не тотожне AB.
[[в цілому, є кш-ізмом 1980-х років, який прийняв баш (та багато інших оболонок). У цьому і вся суть - якщо у вас є[[взагалі , то можете сміливо припускати, що всі розширення ksh, реалізовані навколо неї (fnmatch()-соответствие шаблону стилів, регулярні вирази ERE з=~, і так, придушення розбиття рядків і глобалізація файлової системи) буде в наявності. Оскільки[[синтаксис не POSIX в повному обсязі, додаткової втрати портативності немає, якщо припустити, що функції, з якими він народився, будуть доступні.