Respuestas:
En Bash, test
y [
son conchas incorporadas.
El paréntesis doble , que es una palabra clave de shell, permite una funcionalidad adicional. Por ejemplo, puede utilizar &&
y ||
en lugar de -a
y -o
y hay un operador de expresión regular coincidente =~
.
Además, en una prueba simple, los corchetes dobles parecen evaluarse mucho más rápido que los simples.
$ time for ((i=0; i<10000000; i++)); do [[ "$i" = 1000 ]]; done
real 0m24.548s
user 0m24.337s
sys 0m0.036s
$ time for ((i=0; i<10000000; i++)); do [ "$i" = 1000 ]; done
real 0m33.478s
user 0m33.478s
sys 0m0.000s
Las llaves, además de delimitar un nombre de variable, se usan para la expansión de parámetros, por lo que puede hacer cosas como:
Truncar el contenido de una variable
$ var="abcde"; echo ${var%d*}
abc
Hacer sustituciones similares a sed
$ var="abcde"; echo ${var/de/12}
abc12
Use un valor predeterminado
$ default="hello"; unset var; echo ${var:-$default}
hello
y varios mas
Además, las expansiones de llaves crean listas de cadenas que generalmente se repiten en bucles:
$ echo f{oo,ee,a}d
food feed fad
$ mv error.log{,.OLD}
(error.log is renamed to error.log.OLD because the brace expression
expands to "mv error.log error.log.OLD")
$ for num in {000..2}; do echo "$num"; done
000
001
002
$ echo {00..8..2}
00 02 04 06 08
$ echo {D..T..4}
D H L P T
Tenga en cuenta que las características iniciales de incremento e cero no estaban disponibles antes de Bash 4.
Gracias a gboffi por recordarme sobre expansiones de aparatos ortopédicos.
Los paréntesis dobles se usan para operaciones aritméticas :
((a++))
((meaning = 42))
for ((i=0; i<10; i++))
echo $((a + b + (14 * c)))
y le permiten omitir los signos de dólar en las variables de enteros y matrices e incluyen espacios alrededor de los operadores para facilitar la lectura.
Los corchetes individuales también se usan para los índices de matriz :
array[4]="hello"
element=${array[index]}
Se requieren llaves para las referencias de matriz (¿la mayoría / todas?) En el lado derecho.
El comentario de ephemient me recordó que los paréntesis también se usan para subcapas. Y que se usan para crear matrices.
array=(1 2 3)
echo ${array[1]}
2
:
.
$[expression]
:; esta es la sintaxis de expresión aritmética antigua y obsoleta para la sintaxis preferida más nueva:$((expression))
bash
creación de secuencias, como se menciona periféricamente a continuación ( stackoverflow.com/a/8552128/2749397 ) Como me gustaría comentar un poco esta característica (ya que no lo mencionaste ;-) I ' Me estoy tomando la libertad de usar la respuesta más votada como vehículo ... Dos ejemplos de literales de secuencia: echo {01..12}
-> 01 02 03 04 05 06 07 08 09 10 11 12
(observe el cero inicial); echo {C..Q}
-> C D E F G H I J K L M N O P Q
. Su uso principal es en bucles, por ejemplo, for cnt in {01..12} ; do ... ${cnt} ... ; done
echo {01..12..2}
-> "01 03 05 07 09 11". Gracias por el recordatorio sobre las secuencias. Lo agregaré a mi respuesta.
Un solo paréntesis ( [
) generalmente llama a un programa llamado [
; man test
o man [
para más información Ejemplo:
$ VARIABLE=abcdef
$ if [ $VARIABLE == abcdef ] ; then echo yes ; else echo no ; fi
yes
El paréntesis doble ( [[
) hace lo mismo (básicamente) que un paréntesis simple, pero es un bash incorporado.
$ VARIABLE=abcdef
$ if [[ $VARIABLE == 123456 ]] ; then echo yes ; else echo no ; fi
no
Los paréntesis ( ()
) se usan para crear una subshell. Por ejemplo:
$ pwd
/home/user
$ (cd /tmp; pwd)
/tmp
$ pwd
/home/user
Como puede ver, el subshell le permitió realizar operaciones sin afectar el entorno del shell actual.
(a) Las llaves ( {}
) se utilizan para identificar inequívocamente variables. Ejemplo:
$ VARIABLE=abcdef
$ echo Variable: $VARIABLE
Variable: abcdef
$ echo Variable: $VARIABLE123456
Variable:
$ echo Variable: ${VARIABLE}123456
Variable: abcdef123456
(b) Las llaves también se utilizan para ejecutar una secuencia de comandos en el contexto actual del shell, por ejemplo
$ { date; top -b -n1 | head ; } >logfile
# 'date' and 'top' output are concatenated,
# could be useful sometimes to hunt for a top loader )
$ { date; make 2>&1; date; } | tee logfile
# now we can calculate the duration of a build from the logfile
Sin ( )
embargo, hay una sutil diferencia sintáctica con (ver referencia de bash ); en esencia, un punto y coma ;
después de la última orden entre llaves es una necesidad, y las llaves {
, }
debe estar rodeado por espacios.
[
realidad es una función integrada en Bash, pero se supone que debe actuar /bin/[
como algo opuesto a la función [[
integrada. [[
tiene características diferentes, como operaciones más lógicas y diferentes roles de citas. Además: los paréntesis simples también se usan para matrices, sustitución de procesos y globos extendidos; los paréntesis dobles se usan para la aritmética; Las llaves {}
se utilizan para la agrupación de comandos o multitudes de tipos de expansión de parámetros o expansión de llaves o expansión de secuencia. Estoy seguro de que he perdido algunos otros usos también ...
if [ $VARIABLE == abcdef ]
es un bashismo que, aunque funciona, probablemente debería evitarse; explícitamente use bash ( if [[ ...==...]]
) o deje en claro que está usando el condicional más tradicional ( if [ "$VARIABLE" = "abcdef" ]
). Podría decirse que los scripts deberían comenzar de la manera más simple y portátil posible, hasta que realmente necesiten características específicas de bash (por una razón u otra). Pero en cualquier caso, la intención debe ser clara; "=" y "==" y "[[" y "[" funcionan de manera diferente y su uso debe ser coherente.
[ "$var" = ".."]
lugar de ==
, mientras que en C asignaría en lugar de probar (y es una causa bastante común de errores) ... ¿por qué no 't test
utilizar ==
en lugar de =
? ¿alguien sabe?
/usr/bin/[
no es un enlace simbólico al /usr/bin/test
, y más: ¡estos programas incluso tienen algunos tamaños diferentes!
)
es parte de la case
sintaxis de la declaración para finalizar una línea de caso. No tiene un paréntesis de apertura. Esto me sorprendió la primera vez que lo vi.
Soportes
if [ CONDITION ] Test construct
if [[ CONDITION ]] Extended test construct
Array[1]=element1 Array initialization
[a-z] Range of characters within a Regular Expression
$[ expression ] A non-standard & obsolete version of $(( expression )) [1]
[1] http://wiki.bash-hackers.org/scripting/obsolete
Llaves
${variable} Parameter substitution
${!variable} Indirect variable reference
{ command1; command2; . . . commandN; } Block of code
{string1,string2,string3,...} Brace expansion
{a..z} Extended brace expansion
{} Text replacement, after find and xargs
Paréntesis
( command1; command2 ) Command group executed within a subshell
Array=(element1 element2 element3) Array initialization
result=$(COMMAND) Command substitution, new style
>(COMMAND) Process substitution
<(COMMAND) Process substitution
Paréntesis dobles
(( var = 78 )) Integer arithmetic
var=$(( 20 + 5 )) Integer arithmetic, with variable assignment
(( var++ )) C-style variable increment
(( var-- )) C-style variable decrement
(( var0 = var1<98?9:21 )) C-style ternary operation
Solo quería agregarlos desde TLDP :
~:$ echo $SHELL
/bin/bash
~:$ echo ${#SHELL}
9
~:$ ARRAY=(one two three)
~:$ echo ${#ARRAY}
3
~:$ echo ${TEST:-test}
test
~:$ echo $TEST
~:$ export TEST=a_string
~:$ echo ${TEST:-test}
a_string
~:$ echo ${TEST2:-$TEST}
a_string
~:$ echo $TEST2
~:$ echo ${TEST2:=$TEST}
a_string
~:$ echo $TEST2
a_string
~:$ export STRING="thisisaverylongname"
~:$ echo ${STRING:4}
isaverylongname
~:$ echo ${STRING:6:5}
avery
~:$ echo ${ARRAY[*]}
one two one three one four
~:$ echo ${ARRAY[*]#one}
two three four
~:$ echo ${ARRAY[*]#t}
one wo one hree one four
~:$ echo ${ARRAY[*]#t*}
one wo one hree one four
~:$ echo ${ARRAY[*]##t*}
one one one four
~:$ echo $STRING
thisisaverylongname
~:$ echo ${STRING%name}
thisisaverylong
~:$ echo ${STRING/name/string}
thisisaverylongstring
echo ${#ARRAY}
muestra tres, porque el primer elemento ARRAY
contiene tres caracteres, no porque contiene tres elementos! Para imprimir el número de elementos use echo ${#ARRAY[@]}
.
${TEST:-test}
es igual a $TEST
si la variable TEST
existe, de lo contrario, simplemente devuelve la cadena "prueba". Hay otra versión que hace aún más: ${TEST:=test}
--- que también equivale a $TEST
si TEST existe, pero siempre que no existe, crea la variable TEST
y asigna un valor "prueba" y también se convierte en el valor de toda la expresión.
La diferencia entre test , [ y [[ se explica con gran detalle en BashFAQ .
Para abreviar una larga historia: la prueba implementa la sintaxis antigua y portátil del comando. En casi todos los shells (los shells Bourne más antiguos son la excepción), [es un sinónimo de prueba (pero requiere un argumento final de]). Aunque todos los shells modernos tienen implementaciones integradas de [, generalmente todavía hay un ejecutable externo con ese nombre, por ejemplo / bin / [.
[[es una nueva versión mejorada de la misma, que es una palabra clave, no un programa. Esto tiene efectos beneficiosos sobre la facilidad de uso, como se muestra a continuación. [[es entendido por KornShell y BASH (por ejemplo, 2.03), pero no por POSIX o BourneShell anteriores.
Y la conclusión:
¿Cuándo se debe usar el nuevo comando de prueba [[y cuándo se usa el anterior [? Si la portabilidad al BourneShell es una preocupación, se debe usar la sintaxis anterior. Si, por otro lado, el script requiere BASH o KornShell, la nueva sintaxis es mucho más flexible.
Los paréntesis ()
se utilizan en la definición de funciones:
function_name () { command1 ; command2 ; }
Esa es la razón por la que debe escapar del paréntesis incluso en los parámetros de comando:
$ echo (
bash: syntax error near unexpected token `newline'
$ echo \(
(
$ echo () { command echo The command echo was redefined. ; }
$ echo anything
The command echo was redefined.
unset -f echo
. Ver help unset
.
Truncate the contents of a variable
$ var="abcde"; echo ${var%d*}
abc
Make substitutions similar to sed
$ var="abcde"; echo ${var/de/12}
abc12
Use a default value
$ default="hello"; unset var; echo ${var:-$default}
hello