expr не схоже на дужки (використовується в математиці для явного пріоритету оператора):
expr 3 * (2 + 1)
bash: syntax error near unexpected token `('
Як виразити пріоритет оператора в bash?
expr не схоже на дужки (використовується в математиці для явного пріоритету оператора):
expr 3 * (2 + 1)
bash: syntax error near unexpected token `('
Як виразити пріоритет оператора в bash?
Відповіді:
Ще один спосіб використання letbash вбудований:
$ let a="3 * (2 + 1)"
$ printf '%s\n' "$a"
9
Примітка
Як зазначав @ Stéphane Chazelas , bashвам слід використовувати ((...))арифметику над exprчи letдля розбірливості.
Для переносимості, використовувати $((...))як @Bernhard відповідь .
let. Це не більше, ніж стандартний або портативний, ніж (( a = 3 * (2 + 1) ))(обидва приходять kshі доступні лише в ksh, bash та zsh), і це менш розбірливо або легко цитувати. Використовуйте a=$((3 * (2 + 1)))для переносу.
((a = 3 * (2 + 1) )), одна для переносимості a=$((3 * (2 + 1)))), тому це не записка проти вас чи вашої відповіді, а проти того, що це обрана відповідь та найкращий бомбардир.
a=1 $[a+2]або a=1 b=2 $[a+b]. Чи є їх причиною уникати цього синтаксису?
Ви можете використовувати арифметичне розширення замість цього.
echo "$(( 3 * ( 2 + 1 ) ))"
9
На мою особисту думку, це виглядає трохи приємніше, ніж використання expr.
З man bash
Арифметичне розширення Арифметичне розширення дозволяє оцінити арифметичний вираз і замінити результат. Формат для арифметичного розширення:
$((expression))Вираз трактується так, ніби він знаходиться в подвійних лапках, але подвійний цитат усередині дужок не трактується спеціально. Усі лексеми в виразі зазнають розширення параметрів, розширення рядків, підстановки команд та видалення цитат. Арифметичні розширення можуть бути вкладені.
Оцінювання проводиться за правилами, переліченими нижче, в АРИТМЕТИЧНІЙ ОЦІНКІ. Якщо вираз недійсний, bash друкує повідомлення, що вказує на збій, і заміни не відбувається.
Немає причин використовувати exprдля арифметики в сучасних оболонках.
POSIX визначає $((...))оператора розширення. Таким чином, ви можете використовувати це у всіх сумісних оболонках POSIX (у shвсіх сучасних Unix-like, dash, bash, yash, mksh, zsh, posh, ksh ...).
a=$(( 3 * (2 + 1) ))
a=$((3*(2+1)))
kshтакож запроваджено letвбудований модуль, який передається тим же видом арифметичного виразу, не розгортається в щось, але повертає статус виходу на основі того, вираз вирішує чи 0, як у expr:
if let 'a = 3 * (2 + 1)'; then
echo "$a is non-zero"
fi
Однак, оскільки цитування робить це незручним і не дуже розбірливим (не в тій же мірі, як exprзвичайно), kshтакож введено ((...))альтернативну форму:
if (( a = 3 * (2 + 1) )) && (( 3 > 1 )); then
echo "$a is non-zero and 3 > 1"
fi
((a+=2))
який набагато більш розбірливий і його слід використовувати замість цього.
letі ((...))доступні тільки в ksh, zshі bash. $((...))Синтаксис повинен бути кращим , якщо портативність для інших оболонок необхідна, exprпотрібно тільки для попереднього POSIX Борн-подібних оболонок (зазвичай оболонки Bourne або ранні версії Almquist оболонки).
На фронті, що не знаходиться в Борні, є кілька снарядів із вбудованим арифметичним оператором:
csh/ tcsh(фактично перша оболонка Unix з вбудованою арифметичною оцінкою):
@ a = 3 * (2 + 1)akanga(на основі rc)
a = $:'3 * (2 + 1)'Як зазначає історія, оригінальна версія оболонки Almquist, розміщена на Usenet в 1989 році, мала exprвбудований (фактично об'єднаний з test), але пізніше його було видалено.
: $((a = a*2))?
$((...))зразок zsh, ksh93 або yash.
exprце зовнішня команда, це не особливий синтаксис оболонки. Тому, якщо ви хочете exprпобачити спеціальні символи оболонки, вам потрібно захистити їх від розбору оболонок, цитуючи їх. Крім того, exprпотрібно кожен номер та оператора передавати як окремий параметр. Таким чином:
expr 3 \* \( 2 + 1 \)
Якщо ви не працюєте над антикварною системою Unix 1970-х чи 1980-х, причин для використання є дуже мало expr. У старі часи снаряди не мали вбудованого способу виконання арифметики, і вам довелося exprзамість цього викликати утиліту. Усі оболонки POSIX мають вбудовану арифметику через синтаксис арифметичного розширення .
echo "$((3 * (2 + 1)))"
Конструкція $((…))розширюється до результату арифметичного виразу (записується у десятковій формі). Bash, як і більшість оболонок, підтримує лише цілу арифметичну модуль 2 64 (або модуль 2 32 для старих версій bash та деяких інших оболонок на 32-бітних машинах).
Bash пропонує додатковий синтаксис зручності, коли ви хочете виконувати завдання або перевірити, чи є вираз 0, але не хвилює результат. Ця конструкція також існує в ksh і zsh, але не в звичайному sh.
((x = 3 * (2+1)))
echo "$x"
if ((x > 3)); then …
Крім цілої арифметики, exprпропонується кілька функцій маніпулювання рядками. Вони теж підпадають під функції оболонок POSIX, за винятком однієї: expr STRING : REGEXPперевіряє, чи відповідає рядок вказаному регулярному вираженню. Оболонка POSIX не може це зробити без зовнішніх інструментів, але bash може з [[ STRING =~ REGEXP ]](з іншим синтаксисом regexp - exprкласичний інструмент і використовує BRE, bash використовує ERE).
Якщо ви не підтримуєте сценарії, які працюють у 20-річних системах, вам не потрібно знати, що exprколи-небудь існували. Використовуйте арифметику оболонки.
expr foo : '\(.\)'також робить вилучення тексту. bashРосія BASH_REMATCHдосягає чогось подібного. Він також робить рядкове порівняння, що POSIX [не робить (хоча можна уявити способи використання sortдля цього).
Використовуйте дужки з лапками:
expr 3 '*' '(' 2 '+' 1 ')'
9
Цитати заважають bash інтерпретувати дужки як синтаксис bash.
exprкомандному рядку повинні бути розділені пробілами; тому; наприклад, expr 3 "*" "(2" "+" "1)" не буде працювати . (Крім того, BTW, вам, мабуть, не потрібно цитувати +.)
whileі [[, вони синтаксис. Якби вони були ключовими словами, вони не були б інтерпретовані як такі в аргументах команд. Вам потрібні лапки, щоб bash не розбирав їх, а натомість бачив рядковий літерал.