Risposte:
In Bash, test
e [
sono integrati nella shell.
La parentesi doppia , che è una parola chiave shell, consente funzionalità aggiuntive. Ad esempio, è possibile utilizzare &&
e ||
invece di -a
e -o
e c'è un regolare operatore di espressione di corrispondenza =~
.
Inoltre, in un semplice test, le parentesi quadre doppie sembrano valutare molto più velocemente di quelle singole.
$ 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
Le parentesi graffe, oltre a delimitare un nome di variabile, vengono utilizzate per l' espansione dei parametri in modo da poter fare cose come:
Tronca il contenuto di una variabile
$ var="abcde"; echo ${var%d*}
abc
Rendi le sostituzioni simili a sed
$ var="abcde"; echo ${var/de/12}
abc12
Usa un valore predefinito
$ default="hello"; unset var; echo ${var:-$default}
hello
e molti altri ancora
Inoltre, le espansioni di controvento creano elenchi di stringhe che sono in genere ripetute nei loop:
$ 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
Si noti che le funzioni di zero e incremento iniziali non erano disponibili prima di Bash 4.
Grazie a gboffi per avermi ricordato le espansioni del tutore.
Le doppie parentesi vengono utilizzate per le operazioni aritmetiche :
((a++))
((meaning = 42))
for ((i=0; i<10; i++))
echo $((a + b + (14 * c)))
e consentono di omettere i segni del dollaro sulle variabili intere e array e includere spazi attorno agli operatori per la leggibilità.
Le parentesi singole vengono utilizzate anche per gli indici di array :
array[4]="hello"
element=${array[index]}
Sono richiesti parentesi graffe per (quasi / tutti?) I riferimenti di matrice sul lato destro.
Il commento di ephemient mi ha ricordato che le parentesi sono usate anche per i subshells. E che sono usati per creare array.
array=(1 2 3)
echo ${array[1]}
2
:
.
$[expression]
:; questa è la sintassi dell'espressione aritmetica obsoleta e deprecata per la sintassi più nuova e preferita:$((expression))
bash
è la creazione di sequenze, come indicato di seguito sotto ( stackoverflow.com/a/8552128/2749397 ). Mi sto prendendo la libertà di usare la risposta più votata come veicolo ... Due esempi di letterali di sequenza: echo {01..12}
-> 01 02 03 04 05 06 07 08 09 10 11 12
(nota lo zero iniziale); echo {C..Q}
-> C D E F G H I J K L M N O P Q
. Il suo uso principale è nei loop, ad es. for cnt in {01..12} ; do ... ${cnt} ... ; done
echo {01..12..2}
-> "01 03 05 07 09 11". Grazie per il promemoria sulle sequenze. Lo aggiungerò alla mia risposta.
Una singola parentesi ( [
) di solito in realtà chiama un programma chiamato [
; man test
o man [
per maggiori informazioni. Esempio:
$ VARIABLE=abcdef
$ if [ $VARIABLE == abcdef ] ; then echo yes ; else echo no ; fi
yes
La doppia parentesi ( [[
) fa la stessa cosa (fondamentalmente) di una singola parentesi, ma è un built-in bash.
$ VARIABLE=abcdef
$ if [[ $VARIABLE == 123456 ]] ; then echo yes ; else echo no ; fi
no
Le parentesi ( ()
) vengono utilizzate per creare una subshell. Per esempio:
$ pwd
/home/user
$ (cd /tmp; pwd)
/tmp
$ pwd
/home/user
Come puoi vedere, la subshell ti ha permesso di eseguire operazioni senza influire sull'ambiente della shell corrente.
(a) Le parentesi graffe ( {}
) vengono utilizzate per identificare in modo univoco le variabili. Esempio:
$ VARIABLE=abcdef
$ echo Variable: $VARIABLE
Variable: abcdef
$ echo Variable: $VARIABLE123456
Variable:
$ echo Variable: ${VARIABLE}123456
Variable: abcdef123456
(b) Le parentesi graffe vengono anche utilizzate per eseguire una sequenza di comandi nel contesto della shell corrente , ad es
$ { 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
Vi è tuttavia una sottile differenza sintattica ( )
(vedi riferimento bash ); essenzialmente, una virgola ;
dopo l'ultimo comando tra parentesi graffe è un must, e le bretelle {
, }
deve essere circondato da spazi.
[
realtà è un builtin in Bash, ma dovrebbe agire come /bin/[
al contrario del [[
builtin. [[
ha caratteristiche diverse, come più operazioni logiche e ruoli di quotazione diversi. Inoltre: le parentesi singole vengono utilizzate anche per array, sostituzione di processo e globi estesi; le doppie parentesi sono usate per l'aritmetica; le parentesi graffe {}
vengono utilizzate per il raggruppamento dei comandi o una moltitudine di tipi di espansione dei parametri o espansione delle parentesi graffe o espansione della sequenza. Sono sicuro di aver perso anche altri usi ...
if [ $VARIABLE == abcdef ]
è un basismo che, sebbene funzioni, dovrebbe probabilmente essere evitato; utilizzare esplicitamente bash ( if [[ ...==...]]
) o chiarire che si sta utilizzando il condizionale più tradizionale ( if [ "$VARIABLE" = "abcdef" ]
). Probabilmente, gli script dovrebbero iniziare nel modo più semplice e portatile possibile, fino a quando non hanno davvero bisogno di funzionalità specifiche per bash (per una ragione o per l'altra). Ma in ogni caso, l'intento dovrebbe essere chiaro; "=" e "==" e "[[" e "[" funzionano in modo diverso e il loro utilizzo deve essere coerente.
[ "$var" = ".."]
invece di ==
, mentre in C assegnerebbe invece di test (ed è una causa abbastanza comune di bug) ... perché 't test
utilizzare ==
al posto di =
? qualcuno lo sa?
/usr/bin/[
non è un link simbolico a /usr/bin/test
, e altro ancora: questi programmi hanno anche dimensioni diverse!
)
fa parte della case
sintassi dell'istruzione per terminare una riga del caso. Non ha una parentesi aperta. Questo mi ha gettato via la prima volta che l'ho visto.
Parentesi
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
Parentesi graffe
${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
parentesi
( 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
Parentesi doppie
(( 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
Volevo solo aggiungere questi da 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}
mostra tre, a causa del primo elemento del ARRAY
contiene tre caratteri, non perché contiene tre elementi! Per stampare il numero di elementi utilizzare echo ${#ARRAY[@]}
.
${TEST:-test}
uguale $TEST
se la variabile TEST
esiste, altrimenti restituisce semplicemente la stringa "test". Esiste un'altra versione che fa ancora di più: ${TEST:=test}
--- che equivale anche a $TEST
se TEST esiste, ma ogni volta che non lo fa, crea la variabile TEST
e assegna un valore "test" e diventa anche il valore dell'intera espressione.
La differenza tra test , [ e [[ è spiegata in dettaglio nel BashFAQ .
Per farla breve: test implementa la vecchia sintassi portatile del comando. In quasi tutte le shell (le più vecchie shell Bourne sono l'eccezione), [è sinonimo di test (ma richiede un argomento finale di]). Sebbene tutte le shell moderne abbiano implementazioni integrate di [, di solito esiste ancora un eseguibile esterno con quel nome, ad esempio / bin / [.
[[ne è una nuova versione migliorata, che è una parola chiave, non un programma. Ciò ha effetti benefici sulla facilità d'uso, come mostrato di seguito. [[è compreso da KornShell e BASH (ad es. 2.03), ma non da POSIX o BourneShell precedenti.
E la conclusione:
Quando dovrebbe essere usato il nuovo comando test [[e quando quello vecchio [? Se la portabilità su BourneShell è un problema, è necessario utilizzare la vecchia sintassi. Se invece lo script richiede BASH o KornShell, la nuova sintassi è molto più flessibile.
Le parentesi ()
vengono utilizzate nella definizione della funzione:
function_name () { command1 ; command2 ; }
Questo è il motivo per cui devi sfuggire alle parentesi anche nei parametri di 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
. Vedere 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