expr
no parece gustarle el paréntesis (usado en matemáticas para dar prioridad explícita al operador):
expr 3 * (2 + 1)
bash: syntax error near unexpected token `('
¿Cómo expresar la prioridad del operador en bash?
expr
no parece gustarle el paréntesis (usado en matemáticas para dar prioridad explícita al operador):
expr 3 * (2 + 1)
bash: syntax error near unexpected token `('
¿Cómo expresar la prioridad del operador en bash?
Respuestas:
Otra forma de usar let
bash builtin:
$ let a="3 * (2 + 1)"
$ printf '%s\n' "$a"
9
Nota
Como señaló @ Stéphane Chazelas , bash
debe usar ((...))
para hacer aritmética sobre expr
o let
para legibilidad.
Para la portabilidad, use $((...))
como @Bernhard answer .
let
. No es más estándar o portátil que (( a = 3 * (2 + 1) ))
(ambos provienen ksh
y solo están disponibles en ksh, bash y zsh) y es menos legible o fácil de cotizar. Solía a=$((3 * (2 + 1)))
ser portátil.
((a = 3 * (2 + 1) ))
, otra para la portabilidad a=$((3 * (2 + 1)))
), por lo que no es una nota en su contra o en su respuesta, sino en contra de que sea la respuesta seleccionada y máximo goleador.
a=1 $[a+2]
o a=1 b=2 $[a+b]
. ¿Es su razón para evitar esa sintaxis?
Puede usar la expansión aritmética en su lugar.
echo "$(( 3 * ( 2 + 1 ) ))"
9
En mi opinión personal, esto se ve un poco mejor que usar expr
.
De man bash
Expansión aritmética La expansión aritmética permite la evaluación de una expresión aritmética y la sustitución del resultado. El formato para la expansión aritmética es:
$((expression))
La expresión se trata como si estuviera entre comillas dobles, pero una comilla doble entre paréntesis no se trata especialmente. Todos los tokens en la expresión se someten a expansión de parámetros, expansión de cadena, sustitución de comandos y eliminación de comillas. Las expansiones aritméticas pueden estar anidadas.
La evaluación se realiza de acuerdo con las reglas enumeradas a continuación en EVALUACIÓN ARITMÉTICA. Si la expresión no es válida, bash imprime un mensaje que indica un error y no se produce ninguna sustitución.
No hay razón para usar expr
aritmética en conchas modernas.
POSIX define el $((...))
operador de expansión. Por lo tanto, puede usar eso en todos los shells compatibles con POSIX (el sh
de todos los gustos modernos de Unix, dash, bash, yash, mksh, zsh, posh, ksh ...).
a=$(( 3 * (2 + 1) ))
a=$((3*(2+1)))
ksh
También introdujo un valor let
incorporado que se pasa el mismo tipo de expresión aritmética, no se expande en algo, pero devuelve un estado de salida en función de si la expresión se resuelve en 0 o no, como en expr
:
if let 'a = 3 * (2 + 1)'; then
echo "$a is non-zero"
fi
Sin embargo, como la cita lo hace incómodo y poco legible (no en la misma medida que, expr
por supuesto), ksh
también introdujo una ((...))
forma alternativa:
if (( a = 3 * (2 + 1) )) && (( 3 > 1 )); then
echo "$a is non-zero and 3 > 1"
fi
((a+=2))
que es mucho más legible y debería usarse en su lugar.
let
y ((...))
solo están disponibles en ksh
, zsh
y bash
. Se $((...))
debe preferir la sintaxis si se necesita la portabilidad a otros shells, expr
solo se necesita para los shells pre-POSIX similares a Bourne (típicamente el shell Bourne o las primeras versiones del shell Almquist).
En el frente no Bourne, hay algunos shells con operador aritmético incorporado:
csh
/ tcsh
(en realidad, el primer shell de Unix con evaluación aritmética incorporada):
@ a = 3 * (2 + 1)
akanga
(basado en rc
)
a = $:'3 * (2 + 1)'
Como nota histórica, la versión original del shell Almquist, publicada en Usenet en 1989, tenía una versión expr
incorporada (en realidad se fusionó con test
), pero se eliminó más tarde.
: $((a = a*2))
?
$((...))
como zsh, ksh93 o yash.
expr
es un comando externo, no es una sintaxis especial de shell. Por lo tanto, si desea expr
ver caracteres especiales de shell, debe protegerlos del análisis de shell al citarlos. Además, expr
necesita que cada número y operador se pasen como un parámetro separado. Así:
expr 3 \* \( 2 + 1 \)
A menos que esté trabajando en un sistema antiguo de Unix de los años 1970 u 1980, hay muy pocas razones para usarlo expr
. En los viejos tiempos, los shells no tenían una forma integrada de realizar operaciones aritméticas, y en su lugar había que llamar a la expr
utilidad. Todos los shells POSIX tienen aritmética incorporada a través de la sintaxis de expansión aritmética .
echo "$((3 * (2 + 1)))"
La construcción se $((…))
expande al resultado de la expresión aritmética (escrita en decimal). Bash, como la mayoría de los shells, solo admite aritmética de enteros módulo 2 64 (o módulo 2 32 para versiones anteriores de bash y algunos otros shells en máquinas de 32 bits).
Bash ofrece una sintaxis de conveniencia adicional cuando desea realizar asignaciones o probar si una expresión es 0 pero no le importa el resultado. Esta construcción también existe en ksh y zsh pero no en sh simple.
((x = 3 * (2+1)))
echo "$x"
if ((x > 3)); then …
Además de la aritmética de enteros, expr
ofrece algunas funciones de manipulación de cadenas. Estos también están incluidos en las características de los shells POSIX, excepto uno: expr STRING : REGEXP
prueba si la cadena coincide con la expresión regular especificada. Un shell POSIX no puede hacer esto sin herramientas externas, pero bash puede con [[ STRING =~ REGEXP ]]
(con una sintaxis regexp diferente : expr
es una herramienta clásica y usa BRE, bash usa ERE).
A menos que esté manteniendo scripts que se ejecutan en sistemas de 20 años, no necesita saber que expr
alguna vez existió. Usa aritmética de conchas.
expr foo : '\(.\)'
también hace extracción de texto. bash
's BASH_REMATCH
logra algo similar. También hace una comparación de cadenas, que POSIX [
no hace (aunque uno podría imaginar formas de usar sort
para eso).
Use paréntesis con comillas:
expr 3 '*' '(' 2 '+' 1 ')'
9
Las comillas evitan que bash interprete el paréntesis como sintaxis bash.
expr
línea de comando deben estar separados por espacios; entonces; Por ejemplo, expr 3 "*" "(2" "+" "1)"
no funcionará . (Además, por cierto, probablemente no necesites citar el +
.)
while
y [[
, son sintaxis. Si fueran palabras clave, no se interpretarían como tales en los argumentos de comando. Necesita comillas para que bash no las analice, sino que vea un literal de cadena.