expr
не схоже на дужки (використовується в математиці для явного пріоритету оператора):
expr 3 * (2 + 1)
bash: syntax error near unexpected token `('
Як виразити пріоритет оператора в bash?
expr
не схоже на дужки (використовується в математиці для явного пріоритету оператора):
expr 3 * (2 + 1)
bash: syntax error near unexpected token `('
Як виразити пріоритет оператора в bash?
Відповіді:
Ще один спосіб використання let
bash вбудований:
$ 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 не розбирав їх, а натомість бачив рядковий літерал.