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 letbash builtin:
$ let a="3 * (2 + 1)"
$ printf '%s\n' "$a"
9
Nota
Como @ Stéphane Chazelas apontou , bashvocê deve ((...))fazer aritmética acima exprou letpor 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 kshe 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 expraritmé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 ( shtodos os gostos modernos do Unix, dash, bash, yash, mksh, zsh, posh, ksh ...).
a=$(( 3 * (2 + 1) ))
a=$((3*(2+1)))
kshtambém introduziu um letbuilt-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 é exprclaro), kshtambé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.
lete ((...))estão disponíveis apenas em ksh, zshe bash. A $((...))sintaxe deve ser preferida se a portabilidade para outros shells for necessária, exprapenas 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 exprbuilt-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 exprver caracteres especiais do shell, é necessário protegê-los da análise do shell, citando-os. Além disso, exprprecisa 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 exprutilitá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, exproferece algumas funções de manipulação de string. Eles também são incluídos nos recursos dos shells POSIX, exceto um: expr STRING : REGEXPtesta 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 exprjá existiu. Use aritmética de casca.
expr foo : '\(.\)'também faz extração de texto. bash's BASH_REMATCHconsegue 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.
exprlinha 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 +.)
whilee [[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.