Creo que la recomendación que viste fue para POSIX sh y / o el test
comando que funciona como el [
comando, en lugar de la [[
construcción que apareció en ksh (gracias Stéphane Chazelas por la sugerencia) y también se usa, por ejemplo, en bash, zsh y algunos otros conchas
En la mayoría de los lenguajes, como C, cuando ya se sabe que una cláusula es verdadera o falsa, no hay necesidad de evaluar las partes restantes dependiendo de la operación: si es verdadero no después de un lógico o lo sigue, si es falso no después de un lógico y , etc. Esto, por supuesto, permite detenerse cuando un puntero es NULL y no intentar desreferenciarlo en la siguiente cláusula.
Pero la construcción de sh[ expr1 -o expr2 ]
(incluida la implementación de bash) no hace esto: siempre evalúa ambos lados, cuando uno quisiera que solo se evalúe expr1 . Esto podría haberse hecho por compatibilidad con la test
implementación del comando. Por otro lado, sh ||
y &&
sí siguen el principio habitual: no evaluado si no cambiará el resultado.
Entonces la diferencia a tener en cuenta sería:
: > /tmp/effect #clear effect
if [ 1 -eq 1 -o $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]; then
echo true;
fi
cat /tmp/effect
cuyos rendimientos:
true
or-was-evaluated
Arriba, cada uno [
podría haber sido reemplazado por /usr/bin/[
un alias del test
comando, que se usaba antes de [
incorporarse a los shells.
Mientras que las dos siguientes construcciones:
: > /tmp/effect #clear effect
if [ 1 -eq 1 ] || [ $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]; then
echo true;
fi
cat /tmp/effect
o
: > /tmp/effect #clear effect
if [[ 1 -eq 1 || $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]]; then
echo true;
fi
cat /tmp/effect
Solo cederá true
y dejará effect
vacío: se ||
comporta correctamente y también [[
corrigió este problema.
ACTUALIZAR:
Como comentó @ StéphaneChazelas, perdí varias diferencias relacionadas con la pregunta inicial. Voy a poner aquí el más importante (al menos para mí): prioridad de los operadores.
Si bien el shell no tendrá precedencia:
if true || true && false; then
echo true
else
echo false
fi
rendimientos (porque no hay precedencia y, por lo tanto, primero true || true
se evalúa y luego && false
):
false
dentro [[ ]]
del &&
operador tiene prioridad sobre ||
:
if [[ 1 -eq 1 || 1 -eq 1 && 1 -eq 0 ]]; then
echo true
else
echo false
fi
rendimientos (porque 1 -eq 1 && 1 -eq 0
está agrupado y, por lo tanto, es el segundo miembro de ||
):
true
al menos para ksh , bash , zsh .
Por lo tanto, [[ ]]
ha mejorado el comportamiento sobre ambos [ ]
y los operadores lógicos de shell directo.
[
otest
( no[[
), busque lasOB
etiquetas (vinculadas a la definición "obsoleta") en la especificación POSIX paratest
. Entest
, hay algunos casos patológicos donde puede ser imposible decir si(
o)
está destinado a ser significativo a la sintaxis del comando de prueba o una cadena para ser probados, para que las personas que ignoran los marcadores de obsolescencia y el uso que de sintaxis pueden realmente necesita el contrario-"x$foo"
práctica obsoleta ; con[[
eso no es un problema.