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?
shell
quoting
arithmetic
expr
Nicolas Raoul
fuente
fuente
let
. No es más estándar o portátil que(( a = 3 * (2 + 1) ))
(ambos provienenksh
y solo están disponibles en ksh, bash y zsh) y es menos legible o fácil de cotizar. Solíaa=$((3 * (2 + 1)))
ser portátil.((a = 3 * (2 + 1) ))
, otra para la portabilidada=$((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]
oa=1 b=2 $[a+b]
. ¿Es su razón para evitar esa sintaxis?Puede usar la expansión aritmética en su lugar.
En mi opinión personal, esto se ve un poco mejor que usar
expr
.De
man bash
fuente
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 (elsh
de todos los gustos modernos de Unix, dash, bash, yash, mksh, zsh, posh, ksh ...).ksh
También introdujo un valorlet
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 enexpr
: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:que es mucho más legible y debería usarse en su lugar.
let
y((...))
solo están disponibles enksh
,zsh
ybash
. 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):akanga
(basado enrc
)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ó contest
), pero se eliminó más tarde.fuente
: $((a = a*2))
?$((...))
como zsh, ksh93 o yash.expr
es un comando externo, no es una sintaxis especial de shell. Por lo tanto, si deseaexpr
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í: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 laexpr
utilidad. Todos los shells POSIX tienen aritmética incorporada a través de la sintaxis de expansión aritmética .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.
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.fuente
expr foo : '\(.\)'
también hace extracción de texto.bash
'sBASH_REMATCH
logra algo similar. También hace una comparación de cadenas, que POSIX[
no hace (aunque uno podría imaginar formas de usarsort
para eso).Use paréntesis con comillas:
Las comillas evitan que bash interprete el paréntesis como sintaxis bash.
fuente
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.Si tienes bc ..
fuente