Parêntese na expr aritmética: 3 * (2 + 1) ______ qstntxt ___

%code% parece não gostar de parênteses (usado em matemática para especificar a prioridade do operador):

%pre%

Como expressar a prioridade do operador no bash?

    
______ azszpr149832 ___

Outra maneira de usar %code% bash builtin:

%pre%

Nota

Como @ Stéphane Chazelas apontou , em %code% você deve usar %code% para fazer aritmética %code% ou %code% para legibilidade.

Para portabilidade, use %code% como @Bernhard answer .

    
______ azszpr149830 ___

Você pode usar a expansão aritmética.

%pre%

Na minha opinião pessoal, isso parece um pouco melhor do que usar %code% .

De %code%

%bl0ck_qu0te%     
______ azszpr149916 ___

Não há razão para usar %code% para aritmética em shells modernos.

POSIX define o operador de expansão %code% . Então você pode usar isso em todos os shells compatíveis com POSIX (o %code% de todos os Unix-gostos modernos, traço, bash, yash, mksh, zsh, fino, ksh ...).

%pre%

%code% também introduziu um %code% builtin que é transmitido com o mesmo tipo de expressão aritmética, não expande para algo, mas retorna um status de saída com base em se a expressão é resolvida como 0 ou não, como em %code% :

%pre%

No entanto, como a cotação a torna inábil e não muito legível (não na mesma proporção que %code% , é claro), %code% também introduziu uma forma alternativa %code% :

%pre%

, que é muito mais legível e deve ser usado em seu lugar.

%code% e %code% só estão disponíveis em %code% , %code% e %code% . A sintaxe %code% deve ser preferida se a portabilidade para outros shells for necessária, %code% é necessário apenas para shells pré-POSIX semelhantes a Bourne (normalmente o shell Bourne ou versões antigas do shell Almquist).

Na frente não-Bourne, existem alguns shells com operador aritmético integrado:

  • %code% / %code% (na verdade, o primeiro shell Unix com avaliação aritmética incorporada):

    %pre%
  • %code% (com base em %code% )

    %pre%
  • como uma nota de história, a versão original do shell Almquist, como publicado no usenet em 1989, tinha um %code% construído (na verdade, mesclado com %code% ), mas foi removido posteriormente.

______ azszpr149991 ___

%code% é um comando externo, não é uma sintaxe especial do shell. Portanto, se você quiser que %code% veja os caracteres especiais do shell, será necessário protegê-los da análise do shell, citando-os. Além disso, %code% precisa que cada número e operador sejam passados como um parâmetro separado. Assim:

%pre%

A menos que você esteja trabalhando em um antigo sistema unix dos anos 1970 ou 1980, há muito poucas razões para usar %code% . Antigamente, os shells não tinham uma maneira interna de realizar aritmética, e você precisava chamar o utilitário %code% . Todos os shells POSIX possuem aritmética interna por meio da sintaxe expansão aritmética .

%pre%

A construção %code% se expande para o resultado da expressão aritmética (escrita em decimal). Bash, como a maioria das shells, suporta apenas módulos aritméticos inteiros 2 64 (ou módulo 2 32 para versões mais antigas do bash e algumas outras shells em máquinas de 32 bits). p>

O Bash oferece uma sintaxe de conveniência adicional quando você deseja realizar atribuições ou para testar se uma expressão é 0, mas não se importa com o resultado. Esta construção também existe em ksh e zsh, mas não em sh simples.

%pre%

Além da aritmética inteira, %code% oferece algumas funções de manipulação de string. Eles também são incluídos pelos recursos de shells POSIX, exceto por um: %code% testa se a string corresponde ao regexp especificado. Um shell POSIX não pode fazer isso sem ferramentas externas, mas o bash pode com %code% (com um sintaxe diferente de regexp - %code% é uma ferramenta clássica e usa BRE, bash usa ERE).

A menos que você esteja mantendo scripts executados em sistemas de 20 anos, não é necessário saber que %code% já existiu. Use aritmética de shell.

    
______ azszpr149824 ___

Use parênteses com aspas:

%pre%

As citações evitam que o bash interprete os parênteses como a sintaxe bash.

    
______ azszpr349827 ___

Se você tiver bc ...

%pre%     
___

58

expr parece não gostar de parênteses (usado em matemática para especificar a prioridade do operador):

expr 3 * (2 + 1)
bash: syntax error near unexpected token '('

Como expressar a prioridade do operador no bash?

    
por Nicolas Raoul 12.08.2014 / 08:09

6 respostas

40

Outra maneira de usar let bash builtin:

$ let a="3 * (2 + 1)"
$ printf '%s\n' "$a"
9

Nota

Como @ Stéphane Chazelas apontou , em bash você deve usar ((...)) para fazer aritmética expr ou let para legibilidade.

Para portabilidade, use $((...)) como @Bernhard answer .

    
por 12.08.2014 / 08:40
70

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

Arithmetic Expansion Arithmetic expansion allows the evaluation of an arithmetic expression and the substitution of the result. The format for arithmetic expansion is:

         $((expression))

The expression is treated as if it were within double quotes, but a double quote inside the parentheses is not treated specially. All tokens in the expression undergo parameter expansion, string expansion, command substitution, and quote removal. Arithmetic expansions may be nested.

The evaluation is performed according to the rules listed below under ARITHMETIC EVALUATION. If expression is invalid, bash prints a message indicating failure and no substitution occurs.

    
por 12.08.2014 / 08:33
37

Não há razão para usar expr para aritmética em shells modernos.

POSIX define o operador de expansão $((...)) . Então você pode usar isso em todos os shells compatíveis com POSIX (o sh de todos os Unix-gostos modernos, traço, bash, yash, mksh, zsh, fino, ksh ...).

a=$(( 3 * (2 + 1) ))
a=$((3*(2+1)))

ksh também introduziu um let builtin que é transmitido com o mesmo tipo de expressão aritmética, não expande para algo, mas retorna um status de saída com base em se a expressão é 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 cotação a torna inábil e não muito legível (não na mesma proporçã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 em seu lugar.

let e ((...)) só estão disponíveis em ksh , zsh e bash . A sintaxe $((...)) deve ser preferida se a portabilidade para outros shells for necessária, expr é necessário apenas para shells pré-POSIX semelhantes a Bourne (normalmente o shell Bourne ou versões antigas do shell Almquist).

Na frente não-Bourne, existem alguns shells com operador aritmético integrado:

  • csh / tcsh (na verdade, o primeiro shell Unix com avaliação aritmética incorporada):

    @ a = 3 * (2 + 1)
    
  • akanga (com base em rc )

    a = $:'3 * (2 + 1)'
    
  • como uma nota de história, a versão original do shell Almquist, como publicado no usenet em 1989, tinha um expr construído (na verdade, mesclado com test ), mas foi removido posteriormente.

por 12.08.2014 / 17:41
16

expr é um comando externo, não é uma sintaxe especial do shell. Portanto, se você quiser que expr veja os caracteres especiais do shell, será 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. Assim:

expr 3 \* \( 2 + 1 \)

A menos que você esteja trabalhando em um antigo sistema unix dos anos 1970 ou 1980, há muito poucas razões para usar expr . Antigamente, os shells não tinham uma maneira interna de realizar aritmética, e você precisava chamar o utilitário expr . Todos os shells POSIX possuem aritmética interna por meio da sintaxe expansão aritmética .

echo "$((3 * (2 + 1)))"

A construção $((…)) se expande para o resultado da expressão aritmética (escrita em decimal). Bash, como a maioria das shells, suporta apenas módulos aritméticos inteiros 2 64 (ou módulo 2 32 para versões mais antigas do bash e algumas outras shells em máquinas de 32 bits). p>

O Bash oferece uma sintaxe de conveniência adicional quando você deseja realizar atribuições ou para testar se uma expressão é 0, mas não se importa com o resultado. Esta construção também existe em ksh e zsh, mas não em 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 pelos recursos de shells POSIX, exceto por 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 um sintaxe diferente de regexp - expr é uma ferramenta clássica e usa BRE, bash usa ERE).

A menos que você esteja mantendo scripts executados em sistemas de 20 anos, não é necessário saber que expr já existiu. Use aritmética de shell.

    
por 13.08.2014 / 03:30
12

Use parênteses com aspas:

expr 3 '*' '(' 2 '+' 1 ')'
9

As citações evitam que o bash interprete os parênteses como a sintaxe bash.

    
por 12.08.2014 / 08:09
1

Se você tiver bc ...

echo '3 * (2 + 1)'|bc 
9                                                                    
    
por 07.03.2017 / 20:43