Respostas:
No Bash, test
e [
são shell shell.
O colchete duplo , que é uma palavra-chave shell, permite funcionalidade adicional. Por exemplo, você pode usar &&
e ||
, em vez de -a
e -o
e há um operador de expressão correspondência normal =~
.
Além disso, em um teste simples, colchetes duplos parecem avaliar muito mais rápido que os únicos.
$ 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
Os colchetes, além de delimitar um nome de variável, são usados para a expansão de parâmetros, para que você possa fazer coisas como:
Truncar o conteúdo de uma variável
$ var="abcde"; echo ${var%d*}
abc
Faça substituições semelhantes a sed
$ var="abcde"; echo ${var/de/12}
abc12
Use um valor padrão
$ default="hello"; unset var; echo ${var:-$default}
hello
e vários mais
Além disso, as expansões de chaves criam listas de cadeias que são iteradas em loops:
$ 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
Observe que os principais recursos de zero e incremento não estavam disponíveis antes do Bash 4.
Obrigado a gboffi por me lembrar sobre expansões de braçadeira.
Parênteses duplos são usados para operações aritméticas :
((a++))
((meaning = 42))
for ((i=0; i<10; i++))
echo $((a + b + (14 * c)))
e eles permitem que você omita os sinais de dólar nas variáveis de número inteiro e matriz e inclua espaços em torno dos operadores para facilitar a leitura.
Parênteses únicos também são usados para índices de matriz :
array[4]="hello"
element=${array[index]}
A cinta encaracolada é necessária para (a maioria / todas?) Referências de matriz no lado direito.
O comentário de ephemient me lembrou que os parênteses também são usados para subcamadas. E que eles são usados para criar matrizes.
array=(1 2 3)
echo ${array[1]}
2
:
.
$[expression]
; esta é a sintaxe antiga, obsoleta da expressão aritmética para a sintaxe preferida mais recente:$((expression))
bash
criação de seqüências é a criação de seqüências, como periférico mencionado abaixo ( stackoverflow.com/a/8552128/2749397 ) Como eu gostaria de comentar um pouco esse recurso (como você não mencionou ;-) Eu ' m tendo a liberdade de usar a resposta mais votada como veículo ... Dois exemplos de literais de sequência: echo {01..12}
-> 01 02 03 04 05 06 07 08 09 10 11 12
(observe o zero inicial); echo {C..Q}
-> C D E F G H I J K L M N O P Q
. Seu principal uso é em loops, por exemplo, for cnt in {01..12} ; do ... ${cnt} ... ; done
echo {01..12..2}
-> "01 03 05 07 09 11". Obrigado pelo lembrete sobre sequências. Vou adicioná-lo à minha resposta.
Um único colchete ( [
) geralmente chama um programa chamado [
; man test
ou man [
para mais informações. Exemplo:
$ VARIABLE=abcdef
$ if [ $VARIABLE == abcdef ] ; then echo yes ; else echo no ; fi
yes
O colchete duplo ( [[
) faz a mesma coisa (basicamente) que um colchete único, mas é um bash embutido.
$ VARIABLE=abcdef
$ if [[ $VARIABLE == 123456 ]] ; then echo yes ; else echo no ; fi
no
Parênteses ( ()
) são usados para criar um subshell. Por exemplo:
$ pwd
/home/user
$ (cd /tmp; pwd)
/tmp
$ pwd
/home/user
Como você pode ver, o subshell permitiu executar operações sem afetar o ambiente do shell atual.
(a) Chaves ( {}
) são usadas para identificar inequivocamente variáveis. Exemplo:
$ VARIABLE=abcdef
$ echo Variable: $VARIABLE
Variable: abcdef
$ echo Variable: $VARIABLE123456
Variable:
$ echo Variable: ${VARIABLE}123456
Variable: abcdef123456
(b) Chaves também são usadas para executar uma sequência de comandos no contexto atual do shell, por exemplo
$ { 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
Existe uma diferença sintática sutil com ( )
, no entanto (consulte a referência do bash ); essencialmente, um ponto e vírgula ;
após o último comando dentro de chaves é uma obrigação, e as chaves {
, }
deve ser cercado por espaços.
[
na verdade é um built-in no Bash, mas deve agir como um /bin/[
oposto ao [[
built-in. [[
possui recursos diferentes, como operações mais lógicas e funções de cotação diferentes. Além disso: parênteses únicos também são usados para matrizes, substituição de processos e globs estendidos; parênteses duplos são usados para aritmética; chaves {}
são usadas para agrupamento de comandos ou multidões de tipos de expansão de parâmetro ou expansão de chave ou expansão de sequência. Estou certo de que eu perdi alguns outros usos também ...
if [ $VARIABLE == abcdef ]
é um basismo que - embora funcione - provavelmente deve ser evitado; use explicitamente bash ( if [[ ...==...]]
) ou deixe claro que você está usando a condicional ( if [ "$VARIABLE" = "abcdef" ]
) mais tradicional . Indiscutivelmente, os scripts devem começar o mais simples e portátil possível, até que eles realmente precisem de recursos específicos para o bash (por um motivo ou outro). Mas, em qualquer caso, a intenção deve ser clara; "=" e "==" e "[[" e "[") funcionam de maneira diferente e seu uso deve ser consistente.
[ "$var" = ".."]
vez de ==
, enquanto em C ela atribuiria em vez de testar (e é uma causa bastante comum de bugs) ... por que não 't test
usar ==
em vez de =
? Alguém sabe?
/usr/bin/[
não é um link simbólico para o /usr/bin/test
e mais: esses programas têm até alguns tamanhos diferentes!
)
faz parte da case
sintaxe da instrução para finalizar uma linha de caso. Não possui parênteses de abertura. Isso me assustou na primeira vez que o vi.
Suportes
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
Aparelho Encaracolado
${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ênteses
( 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ênteses duplos
(( 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
$(varname)
não está relacionado à sintaxe do bash. Faz parte da sintaxe Makefile .
Eu só queria adicionar estes do 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}
exibe três, por causa do primeiro elemento do ARRAY
contém três caracteres, não porque ele contém três elementos! Para imprimir o número de elementos, use echo ${#ARRAY[@]}
.
${TEST:-test}
é igual $TEST
se a variável TEST
existir, caso contrário, simplesmente retorna a string "test". Existe outra versão que faz ainda mais: ${TEST:=test}
--- que também é igual a $TEST
se TEST existe, mas sempre que não existe, ela cria a variável TEST
e atribui um valor "test" e também se torna o valor de toda a expressão.
A diferença entre teste , [ e [[ é explicado em grandes detalhes no BashFAQ .
Para resumir uma longa história: test implementa a sintaxe antiga e portátil do comando. Em quase todos os shells (os shells Bourne mais antigos são a exceção), [é sinônimo de teste (mas requer um argumento final de]). Embora todos os shells modernos tenham implementações internas de [, geralmente ainda existe um executável externo com esse nome, por exemplo, / bin / [.
[[é uma nova versão aprimorada, que é uma palavra-chave, não um programa. Isso tem efeitos benéficos na facilidade de uso, como mostrado abaixo. [[é entendido por KornShell e BASH (por exemplo, 2.03), mas não pelo POSIX ou BourneShell mais antigo.
E a conclusão:
Quando o novo comando de teste [[deve ser usado e quando o antigo [? Se a portabilidade para o BourneShell for uma preocupação, a sintaxe antiga deve ser usada. Se, por outro lado, o script exigir BASH ou KornShell, a nova sintaxe será muito mais flexível.
Parênteses ()
estão sendo usados na definição de função:
function_name () { command1 ; command2 ; }
Essa é a razão pela qual você precisa escapar parênteses, mesmo nos 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
. Veja 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