795 Stimmen

Verwendung von doppelten oder einfachen Klammern, Klammern, geschweiften Klammern

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?

715voto

Dennis Williamson Punkte 322329

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

394voto

Carl Norum Punkte 210051
  1. Eine einzelne Klammer ( [ ) ruft normalerweise ein Programm namens [ ; man test o man [ für weitere Informationen. Beispiel:

    $ VARIABLE=abcdef
    $ if [ $VARIABLE == abcdef ] ; then echo yes ; else echo no ; fi
    yes
  2. 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
  3. 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.

  4. (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.

348voto

Yola Punkte 17461

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

24voto

kzh Punkte 18714

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

24voto

fwhacking Punkte 880

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ür test (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.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X