staging.inyokaproject.org

Quantoren in Shell mit if

Status: Gelöst | Ubuntu-Version: Xubuntu 22.04 (Jammy Jellyfish)
Antworten |

Fried-rich

Anmeldungsdatum:
2. Mai 2013

Beiträge: 1162

Hallo,

kann es sein, dass in der Shell mit if keine Quantoren erkannt werden? z. B. geht

1
2
3
4
a=5000
if [[ $a = [0-9][0-9][0-9][0-9] ]]; then
 echo ja
fi

aber das nicht

1
2
3
4
a=5000
if [[ $a = [0-9]{1,4} ]]; then
 echo ja
fi

Ich hab es mit Anführungszeichen und allem möglichen versucht, nichts geht.

Bearbeitet von rklm:

Syntaxhighlighting. Bitte beachte Forum/Syntax und nutze die Vorschaufunktion!

kB Team-Icon

Supporter, Wikiteam
Avatar von kB

Anmeldungsdatum:
4. Oktober 2007

Beiträge: 9837

Das hat nichts mit dem Shell-Schlüsselwort if zu tun, sondern betrifft das erweitere Test-Konstrukt [[ … ]] der Bash.

Dieses non-Posix-Feature kennt drei Muster-Vergleiche für Zeichenketten, ausgedrückt durch die Operatoren == (= ist dafür ein zulässiges Synonym), != (verschieden) und =~. Getestet wird jeweils, ob der konkrete Zeichenkette auf der linken Seite dem Muster auf der rechten Seite entspricht bzw. bei != nicht entspricht.

Als Muster erwarten die beiden ersten Operatoren ein Shell-Glob, der Operator =~ aber einen erweiterten regulären Ausdruck nach Posix.

Somit:

1
2
3
4
5
6
$ a=1234 ; [[ $a =~ ^[0-9]{1,4}$ ]] ; echo $?
0
$ a=12345 ; [[ $a =~ ^[0-9]{1,4}$ ]] ; echo $?
1
$ a=12345 ; [[ $a =~ [0-9]{1,4}$ ]] ; echo $?   # <-- aber
0

Beachte die Grundregel bei regulären Ausdrücken: Diese müssen in der Praxis immer verankert werden, i.d.F. sogar am Anfang und am Ende. Wenn man darauf verzichtet, funktionieren sie natürlich auch, aber in der Regel nicht der Aufgabe entsprechend.

Bearbeitet von rklm:

Syntaxhighlighting.

wxpte

Anmeldungsdatum:
20. Januar 2007

Beiträge: 1388

Für die Benutzung von Quantoren innerhalb einer if-Abfrage steht aber noch ein anderer Weg offen:

1
2
3
4
a=5000
if grep -Eqx '[0-9]{1,4}' <<< $a; then
 echo ja
fi

Bei regulären Ausdrücken eignet sich grep mMn sowieso viel besser, als test.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

wxpte schrieb:

Für die Benutzung von Quantoren innerhalb einer if-Abfrage steht aber noch ein anderer Weg offen:

1
2
3
4
a=5000
if grep -Eqx '[0-9]{1,4}' <<< $a; then
 echo ja
fi

Bei regulären Ausdrücken eignet sich grep mMn sowieso viel besser, als test.

Es gibt auch noch das wenig beachtete expr, das man hier gut verwenden kann, weil es nicht wie grep eine ganze Datei als Eingabe erwartet sondern Zeichenkette und Regex als Argumente bekommt.

1
2
3
4
5
if expr "$a" : '[0-9]\{1,4\}$' >/dev/null; then
  echo ja
else
  echo nein
fi

Fried-rich

(Themenstarter)

Anmeldungsdatum:
2. Mai 2013

Beiträge: 1162

Die erstgenannte Lösung hat funktioniert, die anderen guck ich mir mal an.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

Hatte noch vergessen zu erwähnen, dass die Lösung mit expr POSIX-kompatibel ist und auch in der sh funktioniert. Die doppelten eckigen Klammern brauchen die bash (oder vielleicht auch eine andere Shell wie die zsh).

wxpte

Anmeldungsdatum:
20. Januar 2007

Beiträge: 1388

Auch die eigentliche Ausgabe von expr finde ich interessant:

1
2
3
4
5
6
#!/bin/bash
if stellen=$(expr "$1" : '[0-9]\{1,4\}$'); then
   echo "Die hinterlegte Zahl ist ${stellen}-stellig."
else
   echo 'Die hinterlegte Zahl hat zu viele Stellen und ist daher ungültig.'
fi
$ ./stellen.sh 4810
Die hinterlegte Zahl ist 4-stellig. 
$ ./stellen.sh 12851
Die hinterlegte Zahl hat zu viele Stellen und ist daher ungültig. 
Antworten |