staging.inyokaproject.org

Bash. Case und Wildcard-Bedingungen

Status: Gelöst | Ubuntu-Version: Xubuntu 24.04 (Noble Numbat)
Antworten |

glaskugel

Anmeldungsdatum:
8. Juli 2010

Beiträge: 3850

Es geht um uralte Scripts, die einfach funktionieren. Die sind sehr lange und ich habe keine Ahnung, was da im Detail alles passiert, sind viel zu lang.

Da wird jetzt manchmal mit "case" unterschieden, was ein bestimmter PC tun darf. "uname -n" bestimmte also den Rechnernamen.

Die Frage ist nun kann man die Fälle mit "case" zusammenfassend als Wildcard gruppieren?

Ganz einfaches Beispiel, tatsächlich ist das viel komplizierter.

Also Rechner1, Rechner2, Rechner3 erhält zB eine bestimmte Variable A

Die Namen mit PC1, PC2 erhalten die Variable B.

Bis jetzt wurden dafür 5 Fälle (case) definiert. Kann man das auf 2 "case" reduzieren?

Mir ist klar, das ist sehr allgemein gehalten. Ich habe selber noch keine Ahnung, ob ich die Scripts in dieser Richtung ändern kann. Ich weiß eigentlich nur, wenn "uname -n" sagt, das ist Rechner1, dann wird das Script auf eine bestimme Art ausgeführt und wenn der Name PC1 ist, wird was anderes gemacht als bei Rechner1. Jetzt soll aber ein neuer Rechner genau das gleiche machen wie Rechner1.

Ich will mir ersparen alle Teile mit case durchzuschauen und einfach schauen, ob ich mir durch Gruppierung mir Änderungen ersparen kann. Am liebsten wie bei einer Wildcard, alles wo der Rechnername mit PC beginnt ist eine Gruppe.

Es ist mal nur eine grundsätzliche Frage, was mit "case" möglich ist.

Eigentlich sollte es so funktionieren?

case $rechner in
    PC1|PC2)

Aber geht das auch irgendwie mit einer Wildcard "PC*"

TK87

Anmeldungsdatum:
8. Juli 2019

Beiträge: 266

Moin,

klar kann man bei case wildcards nutzen.

Gruß Thomas

BTW: Das auszuprobieren wäre eigentlich schneller gewesen als den Text zu verfassen.

kB Team-Icon

Supporter, Wikiteam
Avatar von kB

Anmeldungsdatum:
4. Oktober 2007

Beiträge: 9837

glaskugel schrieb:

[…] Es ist mal nur eine grundsätzliche Frage, was mit "case" möglich ist.

case … esac

vergleicht einen Testwert sukzessive mit einer Liste von Vergleichswerten bis zu einer Übereinstimmung und führt dann die diesem passenden Vergleichswert zugeordneten (in der Regel nur diese, aber auch dass lässt sich durch zusätzliche Syntax anders steuern) Befehle aus.

Als Testwert kann man alles verwenden, was nach Auswertung einen String produziert. In der Regel verwendet man eine Variable als Quelle für den Testwert.

Vergleichswerte sind Shell-Globs. Man kann also String-Literale, die Joker-Zeichen * und ?, Zeichenklassen (mit []) und Alternativen (mit |) verwenden. Lediglich Reihung (mit {}) ist nicht sinnvoll anwendbar. Vergleichswerte können auch aus Variablen stammen oder mit Hilfe deren Werte konstruiert werden. Wie üblich müssen Sonderzeichen der Shell in Vergleichswerten quotiert oder maskiert werden.

Eigentlich sollte es so funktionieren?

case $rechner in
    PC1|PC2)

Ja. Ich persönlich bevorzuge allerdings statt der üblichen abgekürzten die vollständige Syntax:

case $Testwert in (PC1|PC2) … ;; (…) ;; (…) ; esac 

Die vollständige Syntax gibt mir vollständige Freiheit über die grafische Gestaltung mit Zeilenumbrüchen, während die übliche abkürzende Syntax Zeilenumbrüche zur Syntax macht.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

Ja, das geht. Siehe die anderen Antworten.

Aber glaskugel, bitte nutze Absätze, um Deinen Text zu strukturieren! Siehe Forum/Syntax und Richtig Fragen (Abschnitt „Sprache“)

glaskugel

(Themenstarter)

Anmeldungsdatum:
8. Juli 2010

Beiträge: 3850

Danke das reicht mir als Antwort, wollte nur wissen ob es möglich ist, dann kann ich mal experimentieren

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

kB schrieb:

Ich persönlich bevorzuge allerdings statt der üblichen abgekürzten die vollständige Syntax:

case $Testwert in (PC1|PC2) … ;; (…) ;; (…) ; esac 

Das ist keine korrekte Syntax: Einträge in der Liste bestehen nur einem oder mehreren durch Pipe getrennten Mustern und einer schließenden Klammer. Siehe die Manpage oder auch help case.

Die vollständige Syntax gibt mir vollständige Freiheit über die grafische Gestaltung mit Zeilenumbrüchen, während die übliche abkürzende Syntax Zeilenumbrüche zur Syntax macht.

Was soll "abkürzende Syntax" bei case sein?

kB Team-Icon

Supporter, Wikiteam
Avatar von kB

Anmeldungsdatum:
4. Oktober 2007

Beiträge: 9837

rklm schrieb:

[…] Das ist keine korrekte Syntax […]

Doch, ist es. Die Manpage von bash spricht über:

case word in [ [(] pattern [ | pattern ] ... ) list ;; ] ... esac

Und es funktioniert auch:

$ A=abc ; case $A in (a*) echo $BASH_VERSION ;; 1*) echo eins ; esac
5.2.21(1)-release
$ A=1abc ; case $A in (a*) echo $BASH_VERSION ;; 1*) echo eins ; esac
eins
$

Bei früheren (sicher bei 3, ich glaube auch noch bei 4) Versionen von Bash hat "1)" (also ohne öffnende Klammer) so nicht funktioniert, sondern nur am Anfang (bis auf whitespace) einer Zeile, also nach einem Zeilenumbruch. Also wurde früher syntaktisch die öffnende Klammer ersetzt durch Zeilenumbruch – diese Sünde scheint aktuell bereinigt zu sein, was mir auch neu ist.

Was soll "abkürzende Syntax" bei case sein?

Aus meiner Sicht gehört zu einer schließenden Klammer immer eine öffnende und umgekehrt, weshalb mir die üblicherweise verwendete Schreibweise immer zuwider war und bleibt. Also „abkürzende Syntax“ im Sinne von: Wir lassen die eigentlich erforderliche öffnende Klammer einfach weg.

Aus meiner Sicht ist die schon immer mögliche, aber ungebräuchliche Schreibweise mit öffnender und schließender Klammer die einzig richtige, auch wenn bash beides akzeptiert.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

kB schrieb:

rklm schrieb:

[…] Das ist keine korrekte Syntax […]

Doch, ist es. Die Manpage von bash spricht über:

case word in [ [(] pattern [ | pattern ] ... ) list ;; ] ... esac

Stimmt, Du hast Recht. Dann haben sie die Ausgabe von help case nicht angepasst.

1
2
3
4
5
6
7
8
9
$ help case
case: case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac
    Execute commands based on pattern matching.
    
    Selectively execute COMMANDS based upon WORD matching PATTERN.  The
    `|' is used to separate multiple patterns.
    
    Exit Status:
    Returns the status of the last command executed.

Potzblitz und es ist sogar ein POSIX Standard! Man lernt nie aus. Danke!

Und es funktioniert auch:

Ich hatte einen Test, der nicht funktioniert hat, aber vermutlich habe ich da einen anderen Fehler eingebaut.

Was soll "abkürzende Syntax" bei case sein?

Aus meiner Sicht gehört zu einer schließenden Klammer immer eine öffnende und umgekehrt, weshalb mir die üblicherweise verwendete Schreibweise immer zuwider war und bleibt. Also „abkürzende Syntax“ im Sinne von: Wir lassen die eigentlich erforderliche öffnende Klammer einfach weg.

Aha. Für mich ist die schließende Klammer einfach das Zeichen, das Muster und Code trennt. Da habe ich mit der fehlenden Balance kein Problem. ☺

Aus meiner Sicht ist die schon immer mögliche, aber ungebräuchliche Schreibweise mit öffnender und schließender Klammer die einzig richtige, auch wenn bash beides akzeptiert.

Ob das immer so war, da wäre ich mir nicht so sicher. Ich vermute, dass die öffnende Klammer optional ist, liegt an der Historie. Vermutlich konnte das eine der früheren Shells nicht.

shiro Team-Icon

Supporter

Anmeldungsdatum:
20. Juli 2020

Beiträge: 1303

Vermutlich konnte das eine der früheren Shells nicht.

Das ist möglich. Die älteste "bash", die ich gerade testen konnte (aus 2005) war "3.2.33(18)-release". Sie unterstützte bereits die "(..)" Form, was allerdings in "man" nicht dokumentiert war.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

Abgefahren! Das ist ja eine richtige Schnitzeljagd. ☺

Antworten |