Ich bin verwirrt über die Verwendung von Klammern, geschweiften Klammern und geschweiften Klammern in der Bash, sowie über den Unterschied zwischen ihren doppelten und einfachen Formen. Gibt es eine klare Erklärung?
Antworten
Zu viele Anzeigen?In Bash, test
y [
sind Shell-Builtins.
El Doppelbügel das ein Shell-Schlüsselwort ist, ermöglicht zusätzliche Funktionen. Sie können zum Beispiel verwenden &&
y ||
anstelle von -a
y -o
und es gibt einen Operator für den regulären Ausdruck =~
.
Außerdem scheinen doppelte eckige Klammern in einem einfachen Test sehr viel schneller auszuwerten als einfache.
$ 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
Die geschweiften Klammern dienen nicht nur zur Abgrenzung eines Variablennamens, sondern auch zur Parametererweiterung damit Sie Dinge tun können wie:
-
Abschneiden des Inhalts einer Variablen
$ var="abcde"; echo ${var%d*} abc
-
Nehmen Sie Ersetzungen vor, ähnlich wie
sed
$ var="abcde"; echo ${var/de/12} abc12
-
Einen Standardwert verwenden
$ default="hello"; unset var; echo ${var:-$default} hello
-
und einige mehr
Außerdem werden durch Klammererweiterungen Listen von Zeichenketten erstellt, über die in der Regel in Schleifen iteriert wird:
$ 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
Beachten Sie, dass die Funktionen für führende Nullen und Inkremente vor Bash 4 nicht verfügbar waren.
Danke an gboffi, der mich an die Klammererweiterungen erinnert hat.
Doppelte Klammern werden verwendet für arithmetische Operationen :
((a++))
((meaning = 42))
for ((i=0; i<10; i++))
echo $((a + b + (14 * c)))
und sie ermöglichen es Ihnen, die Dollarzeichen bei Integer- und Array-Variablen wegzulassen und Leerzeichen um Operatoren herum einzufügen, um die Lesbarkeit zu verbessern.
Einzelne Klammern werden auch verwendet für Array Indizes:
array[4]="hello"
element=${array[index]}
Geschweifte Klammern sind für (die meisten/alle?) Array-Referenzen auf der rechten Seite erforderlich.
ephemisch Kommentar erinnerte mich daran, dass Klammern auch für Subshells verwendet werden. Und dass sie verwendet werden, um Arrays zu erstellen.
array=(1 2 3)
echo ${array[1]}
2
-
Eine einzelne Klammer (
[
) ruft normalerweise ein Programm namens[
;man test
oman [
für weitere Informationen. Beispiel:$ VARIABLE=abcdef $ if [ $VARIABLE == abcdef ] ; then echo yes ; else echo no ; fi yes
-
Die doppelte Klammer (
[[
) tut (im Grunde) das Gleiche wie eine einzelne Klammer, ist aber ein Bash-Builtin.$ VARIABLE=abcdef $ if [[ $VARIABLE == 123456 ]] ; then echo yes ; else echo no ; fi no
-
Klammern (
()
) werden verwendet, um eine Unterschale zu erstellen. Zum Beispiel:$ pwd /home/user $ (cd /tmp; pwd) /tmp $ pwd /home/user
Wie Sie sehen, können Sie mit der Subshell Operationen durchführen, ohne die Umgebung der aktuellen Shell zu beeinflussen.
-
(a) Klammern (
{}
) werden zur eindeutigen Identifizierung von Variablen verwendet. Beispiel:$ VARIABLE=abcdef $ echo Variable: $VARIABLE Variable: abcdef $ echo Variable: $VARIABLE123456 Variable: $ echo Variable: ${VARIABLE}123456 Variable: abcdef123456
(b) Klammern werden auch verwendet, um eine Folge von Befehlen in der aktuell Shell-Kontext, z.B.
$ { 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
Es gibt einen subtilen syntaktischen Unterschied zu ( )
Allerdings (siehe Bash-Referenz ) ; im Wesentlichen ein Semikolon ;
nach dem letzten Befehl in geschweiften Klammern ist ein Muss, und die geschweiften Klammern {
, }
muss von Leerzeichen umgeben sein.
Klammern
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
Gelockte Klammern
${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
Klammern
( 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
Doppelter Klammerausdruck
(( 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
Ich wollte nur hinzufügen, diese von 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
Der Unterschied zwischen Test , [ y [[ wird sehr detailliert erklärt in der BashFAQ . (Hinweis: Der Link zeigt viele Beispiele zum Vergleich)
Um eine lange Geschichte kurz zu machen:
test
implementiert die alte, portable Syntax von des Befehls. In fast allen Shells (die ältesten Bourne-Shells sind die Ausnahme),[
ist ein Synonym fürtest
(erfordert aber ein letztes Argument von]
). Obwohl alle modernen Shells über eingebaute Implementierungen von[
, gibt es in der Regel noch eine externe ausführbare Datei mit diesem Namen, z. B./bin/[
.
[[
ist eine neue, verbesserte Version davon, und es ist ein Schlüsselwort, nicht ein Programm. Dies wirkt sich positiv auf die Benutzerfreundlichkeit aus, wie unten dargestellt.[[
ist von KornShell und BASH (z.B. 2.03) verstanden, aber nicht von den älteren POSIX oder BourneShell.
Und die Schlussfolgerung:
Wann sollte der neue Testbefehl
[[
verwendet werden, und wenn der alte[
? Wenn Portabilität/Konformität zu POSIX oder der BourneShell ein Anliegen ist, sollte die alte Syntax verwendet werden. Wenn das Skript hingegen BASH, Zsh oder KornShell erfordert, ist die neue Syntax in der Regel flexibler.
- See previous answers
- Weitere Antworten anzeigen