# Bash [ ] vs. [[ ]] und = vs. -eq

In der Bash-Shell stolpert man schnell über `[ ]` und `[[ ]]`. Auf den ersten Blick tun beide genau dasselbe: Sie prüfen Bedingungen (z. B. ob eine Datei existiert oder ob zwei Strings gleich sind).

## `[ ]` vs. `[[ ]]`

Der Hauptunterschied ist: **`[` ist ein altes, externes Kommando (bzw. Shell-Builtin), während `[[ ]]` ein modernes, internes Shell-Schlüsselwort ist.**

Gründe, warum man in modernen Bash-Skripten fast immer `[[ ]]` bevorzugen sollte.

### 1. Das einfache `[` (POSIX / Bourne Shell)

Das einfache `[` ist eigentlich ein Synonym für das Kommando `test`. Weil es ein echtes Kommando ist, gelten für es die ganz normalen, strengen Parsing-Regeln der Shell. Das führt oft zu Fehlern.

- **Pflicht zur Quotierung:** Variablen *müssen* in Anführungszeichen gesetzt werden, falls sie leer sind oder Leerzeichen enthalten.
- **Logische Operatoren:** Verknüpfungen wie AND und OR werden mit den alten Flags `-a` und `-o` umgesetzt.

**Beispiel:**

```bash
if [ "$name" = "John Doe" ]; then
    echo "Hallo John"
fi



```

<p class="callout warning">Wenn man hier die Anführungszeichen um `$name` vergisst und die Variable leer ist, stürzt das Skript mit einem Syntaxfehler ab (\\\*\\\*`\\\[: =: unary operator expected`\\\*\\\*).</p>

### 2. Das doppelte `[[ ]]` (Bash-Erweiterung)

`[[ ]]` wurde eingeführt, um das Leben von Entwicklern leichter und Skripte sicherer zu machen. Da es ein eingebautes Schlüsselwort der Bash ist, "sieht" die Shell, was darin passiert, bevor die Variablen aufgelöst werden.

- **Keine Abstürze bei leeren Variablen:** Du musst Variablen nicht zwingend in Anführungszeichen setzen. Wenn `$name` leer ist, funktioniert es trotzdem.
- **Moderne Logik:** Du kannst die ganz normalen Operatoren `&&` (AND) und `||` (OR) verwenden.
- **Pattern Matching &amp; Regex:** Es unterstützt mächtige Vergleiche mit Wildcards (`*`) und regulären Ausdrücken (`~=`).

**Beispiel:**

```bash
if [[ $name == "John Doe" ]]; then
    echo "Hallo John"
fi


```

##### Die wichtigsten Unterschiede im Direktvergleich

<table data-path-to-node="18" id="bkmrk-feature-einfaches-%5B-"><thead><tr><td>\*\*Feature\*\*</td><td>\*\*Einfaches \\\[ (test)\*\*</td><td>\*\*Doppeltes \\\[\\\[ \\\]\\\]\*\*</td></tr></thead><tbody><tr><td><span data-path-to-node="18,1,0,0">\*\*Typ\*\*</span></td><td><span data-path-to-node="18,1,1,0">Befehl / Builtin</span></td><td><span data-path-to-node="18,1,2,0">Shell-Schlüsselwort</span></td></tr><tr><td><span data-path-to-node="18,2,0,0">\*\*Portabilität\*\*</span></td><td><span data-path-to-node="18,2,1,0">\*\*Sehr hoch\*\* (Funktioniert in jeder POSIX-Shell, z.B. `sh`, `dash`)</span></td><td><span data-path-to-node="18,2,2,0">\*\*Eingeschränkt\*\* (Funktioniert in `bash`, `zsh`, `ksh`, aber \*nicht\* in `sh`)</span></td></tr><tr><td><span data-path-to-node="18,3,0,0">\*\*Leere Variablen\*\*</span></td><td><span data-path-to-node="18,3,1,0">Erfordern `"..."`, sonst Syntaxfehler</span></td><td><span data-path-to-node="18,3,2,0">Funktionieren sicher ohne `"..."`</span></td></tr><tr><td><span data-path-to-node="18,4,0,0">\*\*Und / Oder\*\*</span></td><td><span data-path-to-node="18,4,1,0">`-a` (AND) und `-o` (OR)</span></td><td><span data-path-to-node="18,4,2,0">`&amp;&amp;` (AND) und `</span></td></tr><tr><td><span data-path-to-node="18,5,0,0">\*\*Wildcards (Globbing)\*\*</span></td><td><span data-path-to-node="18,5,1,0">Nein</span></td><td><span data-path-to-node="18,5,2,0">Ja (z. B. `\[\[ $file == \*.txt \]\]`)</span></td></tr><tr><td><span data-path-to-node="18,6,0,0">\*\*Regex-Vergleich\*\*</span></td><td><span data-path-to-node="18,6,1,0">Nein</span></td><td><span data-path-to-node="18,6,2,0">Ja (mit dem `~=` Operator)</span></td></tr></tbody></table>

#### Beispiele für die Vorteile von `[[ ]]` 

##### 1. Sicherer Umgang leeren Variablen

```bash
file=""
[ -f $file ]   # FEHLER: bash: [: -f: unary operator expected
[[ -f $file ]] # SICHER: Ergibt einfach "false", kein Absturz.
```

##### 2. Intuitive Logik

```bash
# Beim einfachen [ musst du -a nutzen, oder zwei [ ] verketten:
[ "$A" = "x" ] && [ "$B" = "y" ]

# Bei [[ ]] kannst du es elegant hineinschreiben:
[[ $A == "x" && $B == "y" ]]
```

##### 3. Mustererkennung (Pattern Matching)

Möchtest du prüfen, ob eine Variable mit einem bestimmten Buchstaben endet? Das geht nur mit `[[ ]]`

```bash
version="version_2.0"

if [[ $version == *_2.0 ]]; then
    echo "Es ist Version 2!"
fi
```

#### Fazit

- Schreibst du ein reines **Bash-Skript** (Standard auf den meisten Linux-Systemen, erkennbar am `#!/bin/bash` in der ersten Zeile)? **Nutze immer `[[ ]]`.** Es ist sicherer, moderner und kann mehr.
- Schreibst du ein hochgradig portables Skript, das auch auf eingebetteten Systemen oder alten UNIX-Servern unter der Standard-Shell (`#!/bin/sh`) laufen muss? **Nutze `[`**, aber denke penibel an die Anführungszeichen um deine Variablen.

## `=` vs. `-eq` 

- **`=` (oder `==`):** Wird ausschließlich für **Text (Strings)** verwendet. Es vergleicht die Zeichen alphabetisch/lexikografisch.
- **`-eq`:** Steht für *equal* und wird ausschließlich für **Ganzzahlen (Integers)** verwendet. Es vergleicht den mathematischen Wert.

<p class="callout info">Operatoren mit einem Bindestrich (`-eq`, `-ne`, `-lt`, `-gt`) erwarten immer **Zahlen**.   
Operatoren aus Symbolen (`=`, `==`, `!=`) erwarten immer **Text**.</p>

**Beispiel:**

```bash
A="05"
B="5"

# 1. Textvergleich mit ==
if [[ $A == $B ]]; then
    echo "Text ist gleich"
else
    echo "Text ist UNGLEICH"
fi

# 2. Zahlenvergleich mit -eq
if [[ $A -eq $B ]]; then
    echo "Zahlenwert ist GLEICH"
else
    echo "Zahlenwert ist ungleich"
fi
```

- Der **Textvergleich (`==`) sagt: UNGLEICH!** Warum? Weil die Zeichenkette `"05"` nicht exakt dieselbe ist wie die Zeichenkette `"5"` (die `"0"` am Anfang macht den Unterschied).
- Der **Zahlenvergleich (`-eq`) sagt: GLEICH!** Warum? Weil die Bash beide Werte in Zahlen umwandelt, und mathematisch ist <span class="math-inline" data-index-in-node="115" data-math="05">05</span> exakt dasselbe wie <span class="math-inline" data-index-in-node="137" data-math="5">5</span>.

#### Für Text (Strings)

- `=` oder `==` : Ist gleich? (z. B. `[[ $antwort == "ja" ]]`)
- `!=` : Ist ungleich? (z. B. `[[ $user != "root" ]]`)

#### Für Zahlen (Integers)

- `-eq` : *equal* (gleich) <span class="math-inline" data-index-in-node="21" data-math="\rightarrow">=&gt;</span> `5 -eq 5`
- `-ne` : *not equal* (nicht gleich) <span class="math-inline" data-index-in-node="21" data-math="\rightarrow">=&gt;</span> `5 -ne 3`
- `-lt` : *less than* (kleiner als) <span class="math-inline" data-index-in-node="21" data-math="\rightarrow">=&gt;</span> `3 -lt 5`
- `-le` : *less or equal* (kleiner oder gleich) <span class="math-inline" data-index-in-node="21" data-math="\rightarrow">=&gt;</span> `3 -le 5`
- `-gt` : *greater than* (größer als) <span class="math-inline" data-index-in-node="21" data-math="\rightarrow">=&gt;</span> `5 -gt 3`
- `-ge` : *greater or equal* (größer oder gleich) <span class="math-inline" data-index-in-node="21" data-math="\rightarrow">=&gt;</span> `5 -ge 5`