expr
parece não gostar de parênteses (usado em matemática para prioridade explícita do operador):
expr 3 * (2 + 1)
bash: syntax error near unexpected token `('
Como expressar a prioridade do operador no bash?
expr
parece não gostar de parênteses (usado em matemática para prioridade explícita do operador):
expr 3 * (2 + 1)
bash: syntax error near unexpected token `('
Como expressar a prioridade do operador no bash?
Respostas:
Outra maneira de usar o let
bash builtin:
$ let a="3 * (2 + 1)"
$ printf '%s\n' "$a"
9
Nota
Como @ Stéphane Chazelas apontou , bash
você deve ((...))
fazer aritmética acima expr
ou let
por legibilidade.
Para portabilidade, use $((...))
como a resposta @ Bernhard .
let
. Não é mais padrão ou portátil do que (( a = 3 * (2 + 1) ))
(ambos vêm ksh
e estão disponíveis apenas em ksh, bash e zsh) e é menos legível ou fácil de citar. Use a=$((3 * (2 + 1)))
para ser portátil.
((a = 3 * (2 + 1) ))
e outra para portabilidade a=$((3 * (2 + 1)))
); portanto, não é uma nota contra você ou sua resposta, mas contra a resposta selecionada. e melhor marcador.
a=1 $[a+2]
ou a=1 b=2 $[a+b]
. É o motivo deles para evitar essa sintaxe?
Você pode usar a expansão aritmética.
echo "$(( 3 * ( 2 + 1 ) ))"
9
Na minha opinião pessoal, isso parece um pouco melhor do que usar expr
.
De man bash
Expansão aritmética A expansão aritmética permite a avaliação de uma expressão aritmética e a substituição do resultado. O formato para expansão aritmética é:
$((expression))
A expressão é tratada como se estivesse entre aspas duplas, mas uma aspas dupla entre parênteses não é tratada especialmente. Todos os tokens na expressão passam por expansão de parâmetro, expansão de cadeia, substituição de comando e remoção de cotação. Expansões aritméticas podem ser aninhadas.
A avaliação é realizada de acordo com as regras listadas abaixo em AVALIAÇÃO ARITMÉTICA. Se a expressão for inválida, o bash imprime uma mensagem indicando falha e nenhuma substituição ocorre.
Não há razão para usar expr
aritmética em conchas modernas.
POSIX define o $((...))
operador de expansão. Então você pode usá-lo em todos os shells compatíveis com POSIX ( sh
todos os gostos modernos do Unix, dash, bash, yash, mksh, zsh, posh, ksh ...).
a=$(( 3 * (2 + 1) ))
a=$((3*(2+1)))
ksh
também introduziu um let
built-in que recebe o mesmo tipo de expressão aritmética, não se expande para algo, mas retorna um status de saída com base no fato de a expressão ser resolvida como 0 ou não, como em expr
:
if let 'a = 3 * (2 + 1)'; then
echo "$a is non-zero"
fi
No entanto, como a citação o torna estranho e pouco legível (não na mesma extensão que é expr
claro), ksh
também introduziu uma ((...))
forma alternativa:
if (( a = 3 * (2 + 1) )) && (( 3 > 1 )); then
echo "$a is non-zero and 3 > 1"
fi
((a+=2))
que é muito mais legível e deve ser usado.
let
e ((...))
estão disponíveis apenas em ksh
, zsh
e bash
. A $((...))
sintaxe deve ser preferida se a portabilidade para outros shells for necessária, expr
apenas necessária para shells pré-POSIX tipo Bourne (normalmente o shell Bourne ou versões anteriores do shell Almquist).
Na frente não Bourne, existem algumas conchas com o operador aritmético embutido:
csh
/ tcsh
(na verdade, o primeiro shell Unix com avaliação aritmética integrada):
@ a = 3 * (2 + 1)
akanga
(com base em rc
)
a = $:'3 * (2 + 1)'
como uma nota de histórico, a versão original do shell Almquist, publicada na usenet em 1989, tinha um expr
built-in (na verdade, foi mesclado com test
), mas foi removida mais tarde.
: $((a = a*2))
?
$((...))
como zsh, ksh93 ou yash.
expr
é um comando externo, não é uma sintaxe especial do shell. Portanto, se você deseja expr
ver caracteres especiais do shell, é necessário protegê-los da análise do shell, citando-os. Além disso, expr
precisa que cada número e operador sejam passados como um parâmetro separado. Portanto:
expr 3 \* \( 2 + 1 \)
A menos que você esteja trabalhando em um sistema unix antigo das décadas de 1970 ou 1980, há muito pouco motivo para usar expr
. Antigamente, os shells não tinham uma maneira integrada de executar aritmética, e você precisava chamar o expr
utilitário. Todos os shells POSIX possuem aritmética integrada por meio da sintaxe de expansão aritmética .
echo "$((3 * (2 + 1)))"
A construção se $((…))
expande para o resultado da expressão aritmética (escrita em decimal). O Bash, como a maioria dos shells, suporta apenas o módulo aritmético inteiro 2 64 (ou o módulo 2 32 para versões mais antigas do bash e alguns outros shells em máquinas de 32 bits).
O Bash oferece uma sintaxe de conveniência adicional quando você deseja executar atribuições ou testar se uma expressão é 0, mas não se importa com o resultado. Essa construção também existe no ksh e no zsh, mas não no sh simples.
((x = 3 * (2+1)))
echo "$x"
if ((x > 3)); then …
Além da aritmética inteira, expr
oferece algumas funções de manipulação de string. Eles também são incluídos nos recursos dos shells POSIX, exceto um: expr STRING : REGEXP
testa se a string corresponde ao regexp especificado. Um shell POSIX não pode fazer isso sem ferramentas externas, mas o bash pode com [[ STRING =~ REGEXP ]]
(com uma sintaxe regexp diferente - expr
é uma ferramenta clássica e usa BRE, o bash usa ERE).
A menos que você esteja mantendo scripts executados em sistemas de 20 anos, não é necessário saber que isso expr
já existiu. Use aritmética de casca.
expr foo : '\(.\)'
também faz extração de texto. bash
's BASH_REMATCH
consegue algo similar. Também faz comparação de strings, o que o POSIX [
não faz (embora se possa imaginar maneiras de usá sort
-lo).
Use parênteses com aspas:
expr 3 '*' '(' 2 '+' 1 ')'
9
As aspas impedem que o bash interprete os parênteses como sintaxe do bash.
expr
linha de comando devem ser separados por espaços; tão; por exemplo, expr 3 "*" "(2" "+" "1)"
não vai funcionar . (Também, BTW, você provavelmente não precisa citar o +
.)
while
e [[
são sintaxe. Se fossem palavras-chave, não seriam interpretadas como tal nos argumentos de comando. Você precisa de aspas para que o bash não as analise, mas veja uma string literal.