Discussion:
case, numerische Eingabe mit Punkten
(zu alt für eine Antwort)
Detlef Paschke
2021-05-29 10:48:20 UTC
Permalink
Hallo an alle,

wenn man sich einmal in die Script-Schreiberei verbissen hat kommt man
nur schwer wieder los.
Bei meiner letzten Frage wurde mir hier ja sehr geholfen, auch wenn es
dann etwas ausgeufert ist und ich nicht mehr mitgekommen bin. Meine
Frage wurde aber umfassend beantwortet und das Script arbeitet.

Auch hier weise ich noch einmal darauf hin, dass ich wenig Ahnung vom
Syntax habe und mir jede Zeile und jeden Aufruf einzeln zusammen sammle
und in meine Projekte einbaue.

Nun bastele ich an einer anderen Sache.
Ich habe mich, wie auch bei einer im Script davor gelegenen J/N Abfrage
für eine Schleife entschieden, weil ich nichts gefunden habe, mit if
then bei einer ungültigen Eingabe zurück zur Eingabeaufforderung zu
gelangen. Das geht sicher irgend wie, nur wird der Code für mich dann
sicher unverständlich.

Im betreffenden Script soll eine Versionsnummer abgefragt werden, welche
aus einer unbekannten Anzahl von Zahlen und ebenso unbekannt vielen
Punkten bestehen kann. (NN.NN.NN)

Was ich bis dato zusammenbekommen habe, prüft zumindest erst mal darauf,
dass das erste Zeichen eine Zahl ist. Die Eingabe 1.8.3 geht als
Versionsnummer durch, Programm-1.8.3 würde "raus fliegen".

#!/bin/bash
while true; do
read -p "$(echo -e '\033[32m'Versionsnummer angeben.'\033[0m') " VER
case $VER in
[0-9]* ) echo "Versionsnummer: $VER"; break;;
* ) echo "Keine gültige Versionsnummer";;
esac
done

Nun hätte ich das gern noch etwas präzisieren, so dass ausschließlich
Zahlen und der Punkt als Eingabe akzeptiert werden.
Okay, eigentlich kann es kaum vorkommen aber man weiß ja nie. ;)

Viele Grüße
Detlef Paschke
--
Das "Zitat des Augenblicks" gibt es nur auf
http://schabau.eu
Meine "Merkzettel"
http://helpdesk.schabau.eu
Rupert Haselbeck
2021-05-29 11:04:41 UTC
Permalink
Post by Detlef Paschke
Im betreffenden Script soll eine Versionsnummer abgefragt werden, welche
aus einer unbekannten Anzahl von Zahlen und ebenso unbekannt vielen
Punkten bestehen kann. (NN.NN.NN)
Was ich bis dato zusammenbekommen habe, prüft zumindest erst mal darauf,
dass das erste Zeichen eine Zahl ist. Die Eingabe 1.8.3 geht als
Versionsnummer durch, Programm-1.8.3 würde "raus fliegen".
#!/bin/bash
while true; do
read -p "$(echo -e '\033[32m'Versionsnummer angeben.'\033[0m') " VER
case $VER in
[0-9]* ) echo "Versionsnummer: $VER"; break;;
* ) echo "Keine gültige Versionsnummer";;
esac
done
Nun hätte ich das gern noch etwas präzisieren, so dass ausschließlich
Zahlen und der Punkt als Eingabe akzeptiert werden.
Das kann man auf mannigfaltige Weise bewerkstelligen, z.B. indem man aus
dem Eingabestring alle gültigen Zeichen entfernt und dann prüft, ob ein
leerer String übrigbleibt

etwa so

if [ -n "`echo \"$VER\" | tr -d \"[0-9].\"`" ]; then echo Fehler; fi

MfG
Rupert
Detlef Paschke
2021-05-29 13:16:03 UTC
Permalink
Hallo Rupert,
Post by Rupert Haselbeck
Post by Detlef Paschke
Im betreffenden Script soll eine Versionsnummer abgefragt werden, welche
aus einer unbekannten Anzahl von Zahlen und ebenso unbekannt vielen
Punkten bestehen kann. (NN.NN.NN)
Das kann man auf mannigfaltige Weise bewerkstelligen, z.B. indem man aus
dem Eingabestring alle gültigen Zeichen entfernt und dann prüft, ob ein
leerer String übrigbleibt
etwa so
if [ -n "`echo \"$VER\" | tr -d \"[0-9].\"`" ]; then echo Fehler; fi
aber ich schreibe in meiner Frage doch schon, dass es mir bei einer
falschen Eingabe darum geht, die Anfrage zu wiederholen. Eine Schleife
also. Auch wenn ich es jetzt nicht probiert habe sehe ich doch, dass bei
deinem Beispiel bei Fehleingabe schlicht ein exit erfolgt.
Post by Rupert Haselbeck
MfG
Rupert
Viele Grüße
Detlef Paschke
--
Das "Zitat des Augenblicks" gibt es nur auf
http://schabau.eu
Meine "Merkzettel"
http://helpdesk.schabau.eu
Rupert Haselbeck
2021-05-29 16:00:05 UTC
Permalink
Post by Detlef Paschke
Post by Rupert Haselbeck
Post by Detlef Paschke
Im betreffenden Script soll eine Versionsnummer abgefragt werden, welche
aus einer unbekannten Anzahl von Zahlen und ebenso unbekannt vielen
Punkten bestehen kann. (NN.NN.NN)
Das kann man auf mannigfaltige Weise bewerkstelligen, z.B. indem man aus
dem Eingabestring alle gültigen Zeichen entfernt und dann prüft, ob ein
leerer String übrigbleibt
etwa so
if [ -n "`echo \"$VER\" | tr -d \"[0-9].\"`" ]; then echo Fehler; fi
aber ich schreibe in meiner Frage doch schon, dass es mir bei einer
falschen Eingabe darum geht, die Anfrage zu wiederholen.
Das hab ich durchaus mitbekommen
Post by Detlef Paschke
Eine Schleife also.
Ja
Post by Detlef Paschke
Auch wenn ich es jetzt nicht probiert habe sehe ich doch, dass bei
deinem Beispiel bei Fehleingabe schlicht ein exit erfolgt.
Sorry, ich hatte angenommen, dass das umsetzen auf deine Frage kein
Problem sein sollte.
Eingabe in eine Schleife stellen und Abbruch bei korrektem Eingabewert

| while true
| do
| read -p "$(echo -e '\033[32m'Versionsnummer angeben.'\033[0m') " VER
| [ -n "`echo \"$VER\" | tr -d \"[0-9].\"`" ] || break
| done

MfG
Rupert
Juergen Ilse
2021-06-03 06:40:38 UTC
Permalink
Hallo,
Post by Rupert Haselbeck
Post by Detlef Paschke
Im betreffenden Script soll eine Versionsnummer abgefragt werden, welche
aus einer unbekannten Anzahl von Zahlen und ebenso unbekannt vielen
Punkten bestehen kann. (NN.NN.NN)
Was ich bis dato zusammenbekommen habe, prüft zumindest erst mal darauf,
dass das erste Zeichen eine Zahl ist. Die Eingabe 1.8.3 geht als
Versionsnummer durch, Programm-1.8.3 würde "raus fliegen".
#!/bin/bash
while true; do
read -p "$(echo -e '\033[32m'Versionsnummer angeben.'\033[0m') " VER
case $VER in
[0-9]* ) echo "Versionsnummer: $VER"; break;;
* ) echo "Keine gültige Versionsnummer";;
esac
done
Nun hätte ich das gern noch etwas präzisieren, so dass ausschließlich
Zahlen und der Punkt als Eingabe akzeptiert werden.
Das kann man auf mannigfaltige Weise bewerkstelligen, z.B. indem man aus
dem Eingabestring alle gültigen Zeichen entfernt und dann prüft, ob ein
leerer String übrigbleibt
etwa so
if [ -n "`echo \"$VER\" | tr -d \"[0-9].\"`" ]; then echo Fehler; fi
Dadurch hast du einen Informationsverlust, der in diesem Fall (moeglicher-
weise) relevant ist ... Deine Methode wuerde auch Strings, die mehr als
einen "." in Folge enthalten, als "gueltige Versionsnummer" innterpretieren.

Tschuess,
Juergen Ilse (***@usenet-verwaltung.de)
Michael Ottenbruch
2021-05-29 13:49:08 UTC
Permalink
Post by Detlef Paschke
[...]
Im betreffenden Script soll eine Versionsnummer abgefragt werden, welche
aus einer unbekannten Anzahl von Zahlen und ebenso unbekannt vielen
Punkten bestehen kann. (NN.NN.NN)
Was ich bis dato zusammenbekommen habe, prüft zumindest erst mal darauf,
dass das erste Zeichen eine Zahl ist. Die Eingabe 1.8.3 geht als
Versionsnummer durch, Programm-1.8.3 würde "raus fliegen".
#!/bin/bash
while true; do
read -p "$(echo -e '\033[32m'Versionsnummer angeben.'\033[0m') " VER
case $VER in
[0-9]* ) echo "Versionsnummer: $VER"; break;;
* ) echo "Keine gültige Versionsnummer";;
esac
done
Nun hätte ich das gern noch etwas präzisieren, so dass ausschließlich
Zahlen und der Punkt als Eingabe akzeptiert werden.
Ich hätte gedacht, daß das im letzten Satz Beschriebene äußerst simpel
durch das vergleichsmuster "[0-9\.]*" zu erreichen wäre, da ja der
Backslash die Sonderbedeutung des folgenden Zeichens ("The period .
matches any single character.") aufheben soll. (Das würde dann
allerdings auch auf Muster passen, die mit "." beginnen.)

Das (die Aufhebung) funktioniert aber nicht.

Ohne Backslash funktioniert es auch nicht, was man vielleicht aus: "Most
meta-characters lose their special meaning inside bracket expressions",
schließen könnte. Mit oder Quoting macht der period die RegExp wertlos,
weil er tatsächlich auf jedes beliebige Zeichen matcht.

Ich hätte aber auch vermutet, daß die von Dir verwendete RegExp
ebenfalls nicht das bisher intendierte erreicht, weil sie auch auf eine
leere Zeichenkette matchen würde:
" * The preceding item will be matched zero or more times."
Deswegen hatte ich angenommen, daß da ein "+" hingehörte:
"+ The preceding item will be matched one or more times."

Das war aber auch falsch.

Ich stelle also fest, daß ich bezüglich RegExps noch viel mehr vergessen
habe, als ich ursprünglich schon geglaubt hatte, und daß ich außerdem
langsam zu senil bin, um manpages sinnentnehmend zu lesen. (Alle
manpage-Zitate sind aus dem Abschnitt "REGULAR EXPRESSIONS" der
grep-manpage.)

Ich kann Dir also leider nicht weiterhelfen, wäre aber sehr dankbar,
wenn mir jemand meine Denkfehler erklären könnte.

Der Grundgedanke, an dessen Umsetzung ich so grandios gescheitert bin,
war übrigens der, daß Du zur Lösung Deines Problemes auf "zero oder more
times" '[0-9]+\.?', gefolgt von '[0-9]' prüfen müßtest.

("? The preceding item is optional and matched at most once.")

Das matcht auf mindestens eine Zahl; wenn das Muster mehr als eine Zahl
enthält, muß es mit mindestens einer Zahl beginnen, die von genau einem
Punkt gefolgt werden darf, und dieses Muster darf auch mehrfach
vorkommen, am Ende muß aber wieder mindestens eine Zahl stehen.

Vielleicht hilft wenigstens dieser Ansatz ein bißchen weiter.
--
...und tschuess!

Michael
E-mail: ***@sailor.ping.de
Marcel Logen
2021-05-29 14:44:04 UTC
Permalink
Post by Michael Ottenbruch
Ich kann Dir also leider nicht weiterhelfen, wäre aber sehr dankbar,
wenn mir jemand meine Denkfehler erklären könnte.
IMHO verwechselst Du hier "shell patterns" mit "regexp patterns".

Aus "man bash"
<https://manpages.debian.org/buster/bash/bash.1.en.html>:

| case word in [ [(] pattern [ | pattern ] ... ) list ;; ] ... esac
| A case command first expands word, and tries to match
| it against each pattern in turn, using the matching
| rules described under Pattern Matching below. [...]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

und weiter unten:

| Pattern Matching
|
| Any character that appears in a pattern, other than the special
| pattern characters described below, matches itself. [...]
|
| The special pattern characters have the following meanings:

und dann kommen Erläuterungen zu "*", "?" und "[...]".

Noch weiter unten dann:

| [...] Composite patterns may be formed using one or more of
| the following sub-patterns:
|
| ?(pattern-list)
| Matches zero or one occurrence of the given patterns
| *(pattern-list)
| Matches zero or more occurrences of the given patterns
| +(pattern-list)
| Matches one or more occurrences of the given patterns
| @(pattern-list)
| Matches one of the given patterns
| !(pattern-list)
| Matches anything except one of the given patterns

Damit könnte man sich ein passendes Muster zusammenbauen.

Marcel
--
╭──────╮ ╭───╮ ╭──────╮ ╭─╮ ╭─╮
╭─╯ ╭─╯ ╭─╮ ╰─╮ │ ╰───╮ │ ╭──╯ ╰──╯ ╰──
╭───╮ ╭─╯ ╭───╯ ╭─╮ │ ╰──╮ │ ╰───╮ ╭─╯ ╰──╯
╭────╯ ╰────╯ ╰──────╯ ╰─────╯ ╰─╯ ╰───╯ 2086e7
Michael Ottenbruch
2021-05-29 17:22:02 UTC
Permalink
Post by Marcel Logen
Post by Michael Ottenbruch
Ich kann Dir also leider nicht weiterhelfen, wäre aber sehr dankbar,
wenn mir jemand meine Denkfehler erklären könnte.
IMHO verwechselst Du hier "shell patterns" mit "regexp patterns".
Aus "man bash"
| case word in [ [(] pattern [ | pattern ] ... ) list ;; ] ... esac
| A case command first expands word, and tries to match
| it against each pattern in turn, using the matching
| rules described under Pattern Matching below. [...]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| Pattern Matching
|
| Any character that appears in a pattern, other than the special
| pattern characters described below, matches itself. [...]
|
und dann kommen Erläuterungen zu "*", "?" und "[...]".
| [...] Composite patterns may be formed using one or more of
|
| ?(pattern-list)
| Matches zero or one occurrence of the given patterns
| *(pattern-list)
| Matches zero or more occurrences of the given patterns
| +(pattern-list)
| Matches one or more occurrences of the given patterns
| Matches one of the given patterns
| !(pattern-list)
| Matches anything except one of the given patterns
Damit könnte man sich ein passendes Muster zusammenbauen.
Demnach matcht das von Detlef angegebene Pattern "[0-9]*" nicht auf
"zero or more occurrences" der vorangehenden Range, sondern auf jedes
Muster, das aus einer Zahl und beliebigen darauf folgenden Zeichen
besteht. Und das tut es tatsächlich:

| ***@MO-PC-Home:~ $ cat ~/vertest.0.bsh
| #!/bin/bash
| while true; do
| read -p "$(echo -e '\033[32m'Versionsnummer angeben.'\033[0m') " VER
| case $VER in
| [0-9]* ) echo "Versionsnummer: $VER"; break;;
| * ) echo "Keine gültige Versionsnummer";;
| esac
| done
| ***@MO-PC-Home:~ $ ~/vertest.0.bsh
| Versionsnummer angeben. 5x
| Versionsnummer: 5x
| ***@MO-PC-Home:~ $

Ersetze ich "[0-9]*" durch "*([0-9])", wie es mir nach obiger Anleitung
angezeigt erscheint, kommt ein Syntax error:

| ***@MO-PC-Home:~ $ cat ~/vertest.1.bsh
| #!/bin/bash
| while true; do
| read -p "$(echo -e '\033[32m'Versionsnummer angeben.'\033[0m') " VER
| case $VER in
| *([0-9]) ) echo "Versionsnummer: $VER"; break;;
| * ) echo "Keine gültige Versionsnummer";;
| esac
| done
| ***@MO-PC-Home:~ $ ~/vertest.1.bsh
| /home/skipper/vertest.1.bsh: line 5: syntax error near unexpected token `('
| /home/skipper/vertest.1.bsh: line 5: ` *([0-9]) ) echo "Versionsnummer: $VER"; break;;'
| ***@MO-PC-Home:~ $

Lasse ich die Klammern weg, bin ich genau so schlau wie vorher:

| ***@MO-PC-Home:~ $ cat ~/vertest.1.bsh
| #!/bin/bash
| while true; do
| read -p "$(echo -e '\033[32m'Versionsnummer angeben.'\033[0m') " VER
| case $VER in
| *[0-9.] ) echo "Versionsnummer: $VER"; break;;
| * ) echo "Keine gültige Versionsnummer";;
| esac
| done
| ***@MO-PC-Home:~ $ ~/vertest.1.bsh
| Versionsnummer angeben. test4
| Versionsnummer: test4
| ***@MO-PC-Home:~ $ ~/vertest.1.bsh
| Versionsnummer angeben. test.
| Versionsnummer: test.
| ***@MO-PC-Home:~ $ ~/vertest.1.bsh
| Versionsnummer angeben. testx
| Keine gültige Versionsnummer
| Versionsnummer angeben. test.
| Versionsnummer: test.

Nun matcht das Muster auf eine beliebige Zeichenfolge, gefolgt von einer
Zahl oder einem Punkt.

Ach ja: In der von Dir verkürzt angegbenen Passage der bash-Manpage ist
das ja an eine Voraussetzung geknüpft:

| If the extglob shell option is enabled using the shopt builtin, several extended pattern matching operators
| are recognized. In the following description, a pattern-list is a list of one or more patterns separated by a
| |. Composite patterns may be formed using one or more of the following sub-patterns:

Das ist bei mir der Fall:

| ***@MO-PC-Home:~ $ shopt | grep extglob
| extglob on

Ich glaube, ich habe "composite patterns" in der bash noch nie genutzt,
sondern mich dort immer nur auf "normales" pattern matching beschränkt,
und ansonsten in grep, sed und verwandten Gebieten RegExps verwendet.

Und im Moment habe ich auch nicht den Eindruck, daran noch etwas ändern
zu wollen ... ;-(

Wie gesagt: Mittlerweile zu senil, um manpages sinnentnehmend zu lesen
...
--
...und tschuess!

Michael
E-mail: ***@sailor.ping.de
fritz_s
2021-05-29 15:08:06 UTC
Permalink
Post by Detlef Paschke
#!/bin/bash
while true; do
read -p "$(echo -e '\033[32m'Versionsnummer angeben.'\033[0m') " VER
case $VER in
[0-9]* ) echo "Versionsnummer: $VER"; break;;
* ) echo "Keine gültige Versionsnummer";;
esac
done
[Prosa gelöscht]

ohne case:, geht dann in einer Zeile.

while :
do
read -p ..... VER
[[ $VER == +(+([0-9])\.)+([0-9]) || $VER == +([0-9]) ]] && break
echo Nö
done

HTH
--
fs (***@gmail.com)
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Without facts, the decision cannot be made logically. You must rely on
your human intuition. -- Spock, "Assignment: Earth", stardate unknown
Michael Ottenbruch
2021-05-29 17:55:37 UTC
Permalink
Post by fritz_s
Post by Detlef Paschke
#!/bin/bash
while true; do
read -p "$(echo -e '\033[32m'Versionsnummer angeben.'\033[0m') " VER
case $VER in
[0-9]* ) echo "Versionsnummer: $VER"; break;;
* ) echo "Keine gültige Versionsnummer";;
esac
done
[Prosa gelöscht]
ohne case:, geht dann in einer Zeile.
do
read -p ..... VER
[[ $VER == +(+([0-9])\.)+([0-9]) || $VER == +([0-9]) ]] && break
echo Nö
done
Dann geht aber auch:

while :
do
read -p ..... VER
[[ $VER == *(+([0-9])\.)+([0-9]) ]] && break
echo Nö
done
Post by fritz_s
HTH
Das schon, aber warum das gleiche nicht auch mit case geht, würde mich
ja doch interessieren:

| ***@MO-PC-Home:~ $ cat ~/vertest.2.bsh
| #!/bin/bash
| while :
| do
| read -p "$(echo -e '\033[32m'Versionsnummer angeben.'\033[0m') " VER
| [[ $VER == *(+([0-9])\.)+([0-9]) ]] && break
| echo Keine gültige Versionsnummer
| done
| ***@MO-PC-Home:~ $ ~/vertest.2.bsh
| Versionsnummer angeben. test
| Keine gültige Versionsnummer
| Versionsnummer angeben. 55.55
| ***@MO-PC-Home:~ $ emacs vertest.1.bsh
| ***@MO-PC-Home:~ $ cat ~/vertest.1.bsh
| #!/bin/bash
| while true; do
| read -p "$(echo -e '\033[32m'Versionsnummer angeben.'\033[0m') " VER
| case $VER in
| *(+([0-9])\.)+([0-9]) ) echo "Versionsnummer: $VER"; break;;
| * ) echo "Keine gültige Versionsnummer";;
| esac
| done
| ***@MO-PC-Home:~ $ ~/vertest.1.bsh
| /home/skipper/vertest.1.bsh: line 5: syntax error near unexpected token `('
| /home/skipper/vertest.1.bsh: line 5: ` *(+([0-9])\.)+([0-9]) ) echo "Versionsnummer: $VER"; break;;'

Ich kann nicht behaupten, daß ich das verstünde ...
--
...und tschuess!

Michael
E-mail: ***@sailor.ping.de
Marcel Logen
2021-05-29 19:16:36 UTC
Permalink
Post by Michael Ottenbruch
Das schon, aber warum das gleiche nicht auch mit case geht, würde mich
[...]
Post by Michael Ottenbruch
| #!/bin/bash
| while true; do
| read -p "$(echo -e '\033[32m'Versionsnummer angeben.'\033[0m') " VER
| case $VER in
| *(+([0-9])\.)+([0-9]) ) echo "Versionsnummer: $VER"; break;;
| * ) echo "Keine gültige Versionsnummer";;
| esac
| done
| /home/skipper/vertest.1.bsh: line 5: syntax error near unexpected token `('
| /home/skipper/vertest.1.bsh: line 5: ` *(+([0-9])\.)+([0-9]) ) echo "Versionsnummer: $VER"; break;;'
Ich kann nicht behaupten, daß ich das verstünde ...
Ist hier auch so.

Ich habe es dann mal mit der optionalen öffnenden Klammer ver-
sucht, aber auch das ergibt den gleichen Fehler:

( *(+([0-9]).)+([0-9]) ) echo "Versionsnummer: $VER"; break ;;

Rätselhaft.

Marcel
--
╮ ╭──╮ ╭─╮ ╭────╮ ╭───╮ ╭──╮ ╭──╮ ╭──╮
╰──╯ ╰──╯ │ ╭────╯ │ ╰─╮ │ ╭────╯ ╰──╯ │ ╭─╯ │ ╭──
╰─╮ ╰─╮ ╭────╯ ╭─╯ ╰─╮ │ ╭─────╯ │ ╭─╯ ╭─╮ ╰─╮
╰──────╯ ╰───────╯ ╰─╯ ae3d41╰────────╯ ╰────╯ ╰────╯
Marcel Logen
2021-05-29 19:43:27 UTC
Permalink
Post by Marcel Logen
Post by Michael Ottenbruch
Das schon, aber warum das gleiche nicht auch mit case geht, würde mich
[...]
Post by Marcel Logen
Post by Michael Ottenbruch
Ich kann nicht behaupten, daß ich das verstünde ...
Ist hier auch so.
Ich habe es dann mal mit der optionalen öffnenden Klammer ver-
( *(+([0-9]).)+([0-9]) ) echo "Versionsnummer: $VER"; break ;;
Rätselhaft.
Grmpf!

"shopt -s extglob" im Script ist (doch) die Lösung. Dann klappt
es, auch ohne die optionale Klammer am Anfang.

Marcel
--
╭─╮ ╭────────────╮ ╭───╮ ╭────╮ ╭────────╮
╭──╯ │ ╰─────────╮ ╰───╮ ╭──╯ │ ╰──╮ ╰─╮ ╰────╮ ╰
─╮ ╭─╮ ╭─╯ ╭─╯ ╭─╮ ╭──╮ ╰─╮ ╭─╯ │ ╭───╯ │ │ 837893│
╰────╯ ╰──╯ ╰────╯ ╰─╯ ╰────╯ ╰───╯ ╰───────────╯ ╰───────╯
Marcel Logen
2021-05-29 19:54:14 UTC
Permalink
Post by Marcel Logen
"shopt -s extglob" im Script ist (doch) die Lösung. Dann klappt
es, auch ohne die optionale Klammer am Anfang.
man bash:

| Unless otherwise noted, the shopt options are disabled (unset)
| by default.

Marcel
--
╭───────────╮ ╭──────╮ ╭────╮ ╭───────╮ ╭─╮ ╭
╰─────╮ ╭──╯ ╰────╮ ╰──╮ ╰─╮ │ ╭─╯ ╭─╯ ╭─────╯ ╰──╮ ╭─╮ │
───────╯ │ ╭────╯ │ ╭─╯ │ ╰────╮ ╰──╮ │ ╰────╯ │ │
╰─────╯ ╰──╯ ╰───────╯ ╰──╯ a1c9fe ╰─╯
Christian Weisgerber
2021-05-29 19:47:05 UTC
Permalink
Post by Michael Ottenbruch
Das schon, aber warum das gleiche nicht auch mit case geht, würde mich
| #!/bin/bash
| shopt -s extglob
Post by Michael Ottenbruch
| while true; do
| read -p "$(echo -e '\033[32m'Versionsnummer angeben.'\033[0m') " VER
| case $VER in
| *(+([0-9])\.)+([0-9]) ) echo "Versionsnummer: $VER"; break;;
| * ) echo "Keine gültige Versionsnummer";;
| esac
| done
--
Christian "naddy" Weisgerber ***@mips.inka.de
Michael Ottenbruch
2021-05-29 22:19:28 UTC
Permalink
Post by Christian Weisgerber
Post by Michael Ottenbruch
Das schon, aber warum das gleiche nicht auch mit case geht, würde mich
| #!/bin/bash
| shopt -s extglob
Post by Michael Ottenbruch
| while true; do
| read -p "$(echo -e '\033[32m'Versionsnummer angeben.'\033[0m') " VER
| case $VER in
| *(+([0-9])\.)+([0-9]) ) echo "Versionsnummer: $VER"; break;;
| * ) echo "Keine gültige Versionsnummer";;
| esac
| done
Ich bin doch offensichtlich viel weiter aus der Übung, als ich gedacht
habe. Ich habe ja extra überprüft, ob diese Option gesetzt ist; siehe
<s8tt7r$p68$***@lucy.ping.de>:

| Ach ja: In der von Dir verkürzt angegbenen Passage der bash-Manpage ist
| das ja an eine Voraussetzung geknüpft:
|
| | If the extglob shell option is enabled using the shopt builtin, several extended pattern matching operators
| | are recognized. In the following description, a pattern-list is a list of one or more patterns separated by a
| | |. Composite patterns may be formed using one or more of the following sub-patterns:
|
| Das ist bei mir der Fall:
|
| | ***@MO-PC-Home:~ $ shopt | grep extglob
| | extglob on

Da hat es nicht funktioniert. Setze ich die Option im Skript explizit,
so wie von Dir angegeben, funktioniert es bei mir auch. Warum diese
Option nicht "vererbt" wird, ist mir nicht klar.

Aber auf jeden Fall habe ich heute^Wgestern viel gelernt. :-)

Danke dafür ...
--
...und tschuess!

Michael
E-mail: ***@sailor.ping.de
Christian Weisgerber
2021-05-30 14:04:45 UTC
Permalink
Post by Michael Ottenbruch
| | extglob on
Da hat es nicht funktioniert. Setze ich die Option im Skript explizit,
so wie von Dir angegeben, funktioniert es bei mir auch. Warum diese
Option nicht "vererbt" wird, ist mir nicht klar.
Shelloptionen werden nicht vererbt. (Wie auch?) Weder die klassischen
mit „set“ gesetzten, noch diese „shopt“-Erweiterung der bash.
--
Christian "naddy" Weisgerber ***@mips.inka.de
Michael Ottenbruch
2021-05-30 16:51:49 UTC
Permalink
Post by Christian Weisgerber
Post by Michael Ottenbruch
| | extglob on
Da hat es nicht funktioniert. Setze ich die Option im Skript explizit,
so wie von Dir angegeben, funktioniert es bei mir auch. Warum diese
Option nicht "vererbt" wird, ist mir nicht klar.
Shelloptionen werden nicht vererbt. (Wie auch?) Weder die klassischen
mit „set“ gesetzten, noch diese „shopt“-Erweiterung der bash.
Auch das hatte ich - falls ich es jemals gewußt habe - wohl bereits
wieder vergessen. Aber es bleibt - mindestens für mich als
offensichtlich eher Unbeleckten - die Frage, warum die Option in meiner
Login-Shell gesetzt ist, in der des Skriptes aber nicht.

Was ich mittlerweile herausgefunden habe, ist:

| ***@MO-PC-Home:~ $ set | grep extglob
| BASHOPTS=checkwinsize:cmdhist:complete_fullquote:expand_aliases:extglob:extquote:force_fignore:globasciiranges:histappend:interactive_comments:login_shell:progcomp:promptvars:sourcepath

Ich weiß nur nicht, wo die Variable BASHOPTS gesetzt wird:

| ***@MO-PC-Home:~ $ grep -s extglob \.*
| ***@MO-PC-Home:~ $ grep -s extglob *
| vertest.1.bsh:shopt -s extglob
| ***@MO-PC-Home:~ $ grep -s BASHOPTS *
| ***@MO-PC-Home:~ $ grep -s BASHOPTS \.*
| .lesshst:"BASHOPTS

Oder ganz explizit:

| ***@MO-PC-Home:~ $ grep extglob .profile .bash* .*rc
| ***@MO-PC-Home:~ $ grep extglob /etc/profile /etc/bash* /etc/*rc /etc/profile.d/*
| grep: /etc/bash_completion.d: Is a directory
| ***@MO-PC-Home:~ $ grep BASHOPTS .profile .bash* .*rc
| ***@MO-PC-Home:~ $ grep BASHOPTS /etc/profile /etc/bash* /etc/*rc /etc/profile.d/*
| grep: /etc/bash_completion.d: Is a directory
| ***@MO-PC-Home:~ $

Rätsel über Rätsel ...
--
...und tschuess!

Michael
E-mail: ***@sailor.ping.de
Michael Ottenbruch
2021-05-31 17:01:40 UTC
Permalink
Post by Michael Ottenbruch
Post by Christian Weisgerber
Post by Michael Ottenbruch
| | extglob on
Da hat es nicht funktioniert. Setze ich die Option im Skript explizit,
so wie von Dir angegeben, funktioniert es bei mir auch. Warum diese
Option nicht "vererbt" wird, ist mir nicht klar.
Shelloptionen werden nicht vererbt. (Wie auch?) Weder die klassischen
mit „set“ gesetzten, noch diese „shopt“-Erweiterung der bash.
Auch das hatte ich - falls ich es jemals gewußt habe - wohl bereits
wieder vergessen. Aber es bleibt - mindestens für mich als
offensichtlich eher Unbeleckten - die Frage, warum die Option in meiner
Login-Shell gesetzt ist, in der des Skriptes aber nicht.
| BASHOPTS=checkwinsize:cmdhist:complete_fullquote:expand_aliases:extglob:extquote:force_fignore:globasciiranges:histappend:interactive_comments:login_shell:progcomp:promptvars:sourcepath
Je mehr ich lese, desto weniger verstehe ich. Ich weiß mittlerweile
nicht mehr nur nicht, _wo_ sie gesettzt wird, sondern auch nicht, _wie_:

| BASHOPTS
| A colon-separated list of enabled shell options. Each word in the list is a valid argument for the -s
| option to the shopt builtin command (see SHELL BUILTIN COMMANDS below). The options appearing in
| BASHOPTS are those reported as on by shopt. If this variable is in the environment when bash starts
| up, each shell option in the list will be enabled before reading any startup files. This variable is
| read-only.

Die letzten beiden Sätze lassen mich etwas ratlos zurück. Wie bekomme
ich diese Variable denn ins environment, wenn ich sie a) nicht setzen
kann, sie aber auch b) offensichtlich nicht vererbt wird.

Ich hatte zuerst vermutet, es könnte etwas mit der Frage zu tun haben,
ob die shell eine interaktive shell und/oder eine login-shell ist, finde
diesbezüglich aber keinen Hinweis im "INVOCATION"-Abschnitt der bash.

Meine /etc/profile ist wie ausgeliefert:

| ***@MO-PC-Home:~ $ cat /etc/profile
| # /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
| # and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).
|
| if [ "${PS1-}" ]; then
| if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then
| # The file bash.bashrc already sets the default PS1.
| # PS1='\h:\w\$ '
| if [ -f /etc/bash.bashrc ]; then
| . /etc/bash.bashrc
| fi
| else
| if [ "`id -u`" -eq 0 ]; then
| PS1='# '
| else
| PS1='$ '
| fi
| fi
| fi
|
| if [ -d /etc/profile.d ]; then
| for i in /etc/profile.d/*.sh; do
| if [ -r $i ]; then
| . $i
| fi
| done
| unset i
| fi

Meine ~/.profile ist recht übersichtlich:

| ***@MO-PC-Home:~ $ cat .profile
| # ~/.profile: executed by the command interpreter for login shells.
| # This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
| # exists.
| # see /usr/share/doc/bash/examples/startup-files for examples.
| # the files are located in the bash-doc package.
|
| # the default umask is set in /etc/profile; for setting the umask
| # for ssh logins, install and configure the libpam-umask package.
| #umask 022
|
| # if running bash
| if [ -n "$BASH_VERSION" ]; then
| # include .bashrc if it exists
| if [ -f "$HOME/.bashrc" ]; then
| . "$HOME/.bashrc"
| fi
| fi
|
| # set PATH so it includes user's private bin if it exists
| if [ -d "$HOME/bin" ] ; then
| PATH="$HOME/bin:$PATH"
| fi
|
| # set PATH so it includes user's private bin if it exists
| if [ -d "$HOME/.local/bin" ] ; then
| PATH="$HOME/.local/bin:$PATH"
| fi
|
|
| # links to WIN-Files
| # if [ -d "/mnt/c" ] ; then
| # WIN_PROFILE=$(cmd.exe /C echo %USERPROFILE% 2>/dev/null)
| # WIN_PROFILE_MNT=$(wslpath -u ${WIN_PROFILE/[$'\r\n']})
| # ln -s $WIN_PROFILE_MNT/Downloads ~/Downloads
| # ln -s $WIN_PROFILE_MNT/Dokumente ~/Dokumente
| # fi

Ich finde in beiden nichts, was beim Aufruf als interaktive Shell da
etwas verändern sollte; und an der .bashrc kann es ja auch nicht liegen,
die wird ja auch von .profile gesourced.

Ein simpler Test ergibt:

| ***@MO-PC-Home:~ $ cat ~/bashopts-test.bsh
| #!/bin/bash
| #
| # Testen der BASHOPTS-Variable und wie sie vererbt wird
| #
|
| echo Aufrufparameter: $-
| # grep $(whoami) /etc/passwd
| # echo BASH: $BASH
| # echo BASH_VERSION: $BASH_VERSION
| # echo UID: $UID
| # echo EUID: $EUID
| # echo OSTYPE $OSTYPE
| echo BASH_ENV: $BASH_ENV
| echo ENV: $ENV
| echo SHLVL: $SHLVL
| echo BASHOPTS: $BASHOPTS
|
|
| ***@MO-PC-Home:~ $ . ~/bashopts-test.bsh && echo ---; ~/bashopts-test.bsh
| Aufrufparameter: himBHs
| BASH_ENV:
| ENV:
| SHLVL: 1
| BASHOPTS: checkwinsize:cmdhist:complete_fullquote:expand_aliases:extglob:extquote:force_fignore:globasciiranges:histappend:interactive_comments:login_shell:progcomp:promptvars:sourcepath
| ---
| Aufrufparameter: hB
| BASH_ENV:
| ENV:
| SHLVL: 2
| BASHOPTS: checkwinsize:cmdhist:complete_fullquote:extquote:force_fignore:globasciiranges:hostcomplete:interactive_comments:progcomp:promptvars:sourcepath

Die Inhalte von $BASHOPTS unterscheiden sich also deutlich, je nach
$SHLVL bzw. Aufrufparametern; soweit ich die manpage verstehe, können es
aber auch nicht die zusätzlichen Aufrufparameter der login-shell sein:

| -i If the -i option is present, the shell is interactive.

| -m Monitor mode. Job control is enabled. This option is on by default for interactive shells on
| systems that support it (see JOB CONTROL above). All processes run in a separate process
| group. When a background job completes, the shell prints a line containing its exit status.

| -H Enable ! style history substitution. This option is on by default when the shell is interac-
| tive.

| -s If the -s option is present, or if no arguments remain after option processing, then commands are
| read from the standard input. This option allows the positional parameters to be set when invoking
| an interactive shell or when reading input through a pipe.

Ich werde einfach nicht schlau aus der Sache ...
--
...und tschuess!

Michael
E-mail: ***@sailor.ping.de
Thomas Dorner
2021-05-31 19:54:04 UTC
Permalink
Post by Michael Ottenbruch
Je mehr ich lese, desto weniger verstehe ich. Ich weiß mittlerweile
| BASHOPTS
| A colon-separated list of enabled shell options. Each
| word in the list is a valid argument for the -s
| option to the shopt builtin command (see SHELL BUILTIN
| COMMANDS below). The options appearing in
| BASHOPTS are those reported as on by shopt. If this
| variable is in the environment when bash starts
| up, each shell option in the list will be enabled
| before reading any startup files. This variable is
| read-only.
Die letzten beiden Sätze lassen mich etwas ratlos zurück. Wie bekomme
ich diese Variable denn ins environment, wenn ich sie a) nicht setzen
kann, sie aber auch b) offensichtlich nicht vererbt wird.
Ich gehe davon aus, daß das eine "magische" Variable ist, die per
"shopt" (bzw. der "-O" Option der Shell) verändert wird. Und read-only
heißt ja nicht, daß man sie nicht mittels EXPORT an aufgerufene Shells
weitergeben kann. Per Default ist sie halt nicht exportiert.

Viele Grüße, Thomas
--
Adresse gilt nur kurzzeitig!
Christian Weisgerber
2021-05-31 19:30:44 UTC
Permalink
Post by Michael Ottenbruch
| BASHOPTS are those reported as on by shopt. If this variable is in the environment when bash starts
| up, each shell option in the list will be enabled before reading any startup files. This variable is
| read-only.
Die letzten beiden Sätze lassen mich etwas ratlos zurück. Wie bekomme
ich diese Variable denn ins environment, wenn ich sie a) nicht setzen
kann, sie aber auch b) offensichtlich nicht vererbt wird.
Ah, mittels BASHOPTS gibt es also einen Mechanismus, um shopt zu
vererben.

Shell-Variablen werden nicht automatisch vererbt:
$ FOO=bar

Dazu muss man sie ins Environment exportieren:
$ export FOO

Also: export BASHOPTS
Ich nehme an, irgendwo in deinem Dickicht von Konfigurationsdateien
wird „shopt -s extglob“ gesetzt. *schulterzuck*
--
Christian "naddy" Weisgerber ***@mips.inka.de
Michael Ottenbruch
2021-05-31 22:29:19 UTC
Permalink
Post by Christian Weisgerber
Post by Michael Ottenbruch
| BASHOPTS are those reported as on by shopt. If this variable is in the environment when bash starts
| up, each shell option in the list will be enabled before reading any startup files. This variable is
| read-only.
Die letzten beiden Sätze lassen mich etwas ratlos zurück. Wie bekomme
ich diese Variable denn ins environment, wenn ich sie a) nicht setzen
kann, sie aber auch b) offensichtlich nicht vererbt wird.
Ah, mittels BASHOPTS gibt es also einen Mechanismus, um shopt zu
vererben.
$ FOO=bar
$ export FOO
Das ist mir schon klar. Allerdings kann man BASHOPTS - wie in der
manpage ausgeführt - nicht verändern:

| ***@MO-PC-Home:~ $ BASHOPTS=test:$BASHOPTS
| -bash: BASHOPTS: readonly variable
Post by Christian Weisgerber
Also: export BASHOPTS
Ich nehme an, irgendwo in deinem Dickicht von Konfigurationsdateien
wird „shopt -s extglob“ gesetzt. *schulterzuck*
Meine Frage ist: Wo?

Ich habe in <s90fr5$es4$***@lucy.ping.de> gezeigt, daß in meinen
Konfigurationsdateien (und denen in der bash-manpage unter INVOCATION
genannten) weder "extglob" noch "BASHOPTS" vorkommen. Aus den
verschiedenen Reaktionen auf das Ausgangsposting
<s8t65j$47h$***@solani.org> ist ersichtlich, daß das nicht an einer
exotischen Konfiguration meinerseits liegt, sondern andere Systeme
gleich reagieren.

Man könnte die Frage auch andersherum stellen: In welcher Dokumentation
kann ich nachlesen, mit welchen Optionen die Shell unter welchen
Umständen gestartet wird?

In der bash-manpage heißt es unter SHELL BUILTIN COMMANDS zu shopt

| If either -s or -u is used with no optname arguments, shopt shows only those options which are set or
| unset, respectively. Unless otherwise noted, the shopt options are disabled (unset) by default.
|
|[...]
|
| extglob If set, the extended pattern matching features described above under Pathname Expansion are en-
| abled.

Da steht nicht, daß extglob "by default" gesetzt ist.

Trotzdem ist es bei der beim Systemstart gestarteten Shell gesetzt, die
- bei mir, ausweislich der Variable $- - mit den Parametern "himBHs"
gestartet wurde, in der Subshell mit den Parametern "hB" jedoch nicht,
wie nach der manpage auch zu vermuten.

Bei den in Parametern, mit denen die erste Shell gestartet wurde, die
Subshell aber nicht (also "imHs"), steht in der manpage nichts davon,
daß sie irgendeine shopt-Option setzen oder BASHOPTS verändern.

Ich würde das schon gerne verstehen ...
--
...und tschuess!

Michael
E-mail: ***@sailor.ping.de
Michael Ottenbruch
2021-06-01 20:15:51 UTC
Permalink
Post by Michael Ottenbruch
[...]
Post by Christian Weisgerber
Ich nehme an, irgendwo in deinem Dickicht von Konfigurationsdateien
wird „shopt -s extglob“ gesetzt. *schulterzuck*
Meine Frage ist: Wo?
Konfigurationsdateien (und denen in der bash-manpage unter INVOCATION
genannten) weder "extglob" noch "BASHOPTS" vorkommen. Aus den
verschiedenen Reaktionen auf das Ausgangsposting
exotischen Konfiguration meinerseits liegt, sondern andere Systeme
gleich reagieren.
Man könnte die Frage auch andersherum stellen: In welcher Dokumentation
kann ich nachlesen, mit welchen Optionen die Shell unter welchen
Umständen gestartet wird?
[...]
Ich würde das schon gerne verstehen ...
In /usr/share/bash-completion/bash_completion finden sich die Zeilen:

| # Turn on extended globbing and programmable completion
| shopt -s extglob progcomp

Dies geschieht innerhalb einer Schleifenkonstruktion, die unter anderem
auf die Interaktivität der bash prüft, und zwar sinnigerweise mit der
Prüfung

| "x${PS1-}" != x

Es wird also nicht etwa auf einen Aufrufparameter geprüft, sondern
darauf, ob PS1 gesetzt ist, was bekanntlich per default nur bei
interaktiven Shells der Fall ist. Ich wußte auch mal, wo dann die
Variable PS1 erstmalig gesetzt wird, bin jetzt aber zu faul, es
herauszusuchen.

Die Datei /usr/share/bash-completion/bash_completion wird wiederum von
/etc/profile.d/bash_completion.sh aufgerufen, diese (wie alle anderen im
Verzeichnis /etc/profile.d/) von /etc/profile.

So kommen die Optionen extglob und progcomp ins Environment von
interaktiven Shells.

Wer suchet, der findet ...
--
...und tschuess!

Michael
E-mail: ***@sailor.ping.de
Michael Ottenbruch
2021-06-01 20:58:48 UTC
Permalink
Post by Michael Ottenbruch
| # Turn on extended globbing and programmable completion
| shopt -s extglob progcomp
Dies geschieht innerhalb einer Schleifenkonstruktion, [...]
Die Datei /usr/share/bash-completion/bash_completion wird wiederum von
/etc/profile.d/bash_completion.sh aufgerufen, diese (wie alle anderen im
Verzeichnis /etc/profile.d/) von /etc/profile.
So kommen die Optionen extglob und progcomp ins Environment von
interaktiven Shells.
Das ist doch nicht ganz richtig.

Die innerste der o.g. "Schleifenkonstruktion" sieht so aus:

| if shopt -q progcomp && [ -r /usr/share/bash-completion/bash_completion ]; then
| # Source completion code.
| . /usr/share/bash-completion/bash_completion
| fi

Das heißt, daß (mindestens) durch diesen Aufruf von
/usr/share/bash-completion/bash_completion) nur die Option extglob (aber
um diese ging es ja eigentlich auch) gesetzt wird, nicht aber progcomp,
denn dieser Aufruf wird ja nur erreicht, wenn die Option progcomp
bereits gesetzt ist.
--
...und tschuess!

Michael
E-mail: ***@sailor.ping.de
Christian Weisgerber
2021-06-01 21:02:14 UTC
Permalink
Post by Michael Ottenbruch
Dies geschieht innerhalb einer Schleifenkonstruktion, die unter anderem
auf die Interaktivität der bash prüft, und zwar sinnigerweise mit der
Prüfung
| "x${PS1-}" != x
Wenn PS1 ungesetzt ist und damit zu nichts expandieren würde, wird
stattdessen nichts eingesetzt. Aha. :->

Interaktive Shells haben die Shelloption i gesetzt. Kann man also
seit vier Jahrzehnten z.B. so

case $- in *i*) echo interactive ;; esac

prüfen. Das funktioniert dann mit beliebigen Shells der Bourne-Familie,
anders als

sh -c 'echo ${PS1-unset}'
$
--
Christian "naddy" Weisgerber ***@mips.inka.de
Michael Ottenbruch
2021-06-01 22:31:04 UTC
Permalink
Post by Christian Weisgerber
Post by Michael Ottenbruch
Dies geschieht innerhalb einer Schleifenkonstruktion, die unter anderem
auf die Interaktivität der bash prüft, und zwar sinnigerweise mit der
Prüfung
| "x${PS1-}" != x
Wenn PS1 ungesetzt ist und damit zu nichts expandieren würde, wird
stattdessen nichts eingesetzt. Aha. :->
Das ist mir schon klar, wenn ich auch offen gestanden den Sinn nicht
verstehe, Für meine beschränkten Kenntnisse würden

| "x${PS1}" != x

oder gar

| [[ -z ${PS1} ]]

zum gleichen Ergebnis führen.

Und da die gesamte Prüfung so aussieht:

| if [ "x${BASH_VERSION-}" != x -a "x${PS1-}" != x -a "x${BASH_COMPLETION_VERSINFO-}" = x ]; then

, kann es ja eigentlich auch nicht um Kompatibilität mit irgendwelchen
alten bash-Versionen oder gar anderen Shells als der bash gehen; aber da
will ich mich nicht so weit aus dem Fenster lehnen, weil ich - wie
erwähnt - in meiner mehrjährigen Unix-Pause doch wohl einiges vergessen
zu haben scheine ...
Post by Christian Weisgerber
Interaktive Shells haben die Shelloption i gesetzt. Kann man also
seit vier Jahrzehnten z.B. so
case $- in *i*) echo interactive ;; esac
prüfen. Das funktioniert dann mit beliebigen Shells der Bourne-Familie,
anders als
sh -c 'echo ${PS1-unset}'
$
Ähh, ja. Genau deswegen ja mein "sinnigerweise", und deshalb wundere ich
mich im nächsten, von Dir nicht mehr gequoteten Satz:

| Es wird also nicht etwa auf einen Aufrufparameter geprüft, sondern
| darauf, ob PS1 gesetzt ist, [...]

Die Dateien, aus denen ich hier Ausschnitte zitiert habe, stammen
sämtlich aus einer - diesbezüglich völlig unveränderten - aktuellen
Ubuntu-Installation (Ubuntu 20.04.2 LTS (GNU/Linux
5.4.72-microsoft-standard-WSL2 x86_64)).

Das darf man - finde ich - durchaus erstaunlich finden ...
--
...und tschuess!

Michael
E-mail: ***@sailor.ping.de
Helmut Waitzmann
2021-06-02 06:04:00 UTC
Permalink
Post by Michael Ottenbruch
Post by Christian Weisgerber
Post by Michael Ottenbruch
| "x${PS1-}" != x
Wenn PS1 ungesetzt ist und damit zu nichts expandieren würde,
wird stattdessen nichts eingesetzt. Aha. :->
Das ist mir schon klar, wenn ich auch offen gestanden den Sinn
nicht verstehe, Für meine beschränkten Kenntnisse würden
| "x${PS1}" != x
oder gar
| [[ -z ${PS1} ]]
zum gleichen Ergebnis führen.
Solange die Shell‐Option «-u» (die den Shell anweist, das
Expandieren nicht vorhandener Shell‐Variabler als Fehler anzusehen)
nicht eingeschaltet ist, ist «${var}» das gleiche wie «${var-}»,
ja.
Post by Michael Ottenbruch
| if [ "x${BASH_VERSION-}" != x -a "x${PS1-}" != x -a "x${BASH_COMPLETION_VERSINFO-}" = x ]; then
Darin, wie man lesbaren und robusten Code schreibt, könnte der Autor
noch etwas Nachhilfe vertragen.
Post by Michael Ottenbruch
, kann es ja eigentlich auch nicht um Kompatibilität mit
irgendwelchen alten bash-Versionen oder gar anderen Shells als der
bash gehen;
Wenn es darum nicht ginge, wäre der Test, ob es die Variable
«BASH_VERSION» gibt und ihr Inhalt nicht leer ist, unnötig.  Da der
Test aber gemacht wird, muss ich daraus schließen, dass dieses Stück
Code auch bei anderen Shells zu einem vernünftigen Ergebnis kommen
soll.

Ein Aufruf des Kommandos «test» mit mehr als 4 Parametern oder ein
Aufruf des Kommandos «[» mit mehr als 5 Parametern ist vom
POSIX‐Standard nicht gedeckt.  (Genaueres steht in
<https://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html#top>.) 
Demnach könnte es also durchaus sein, dass ein zu POSIX kompatibler
Shell, der kein «bash» ist, hier fälschlicherweise zum Ergebnis
«ich bin ein interaktiver Bash» kommt.
Post by Michael Ottenbruch
aber da will ich mich nicht so weit aus dem Fenster lehnen, weil
ich - wie erwähnt - in meiner mehrjährigen Unix-Pause doch wohl
einiges vergessen zu haben scheine ...
Post by Christian Weisgerber
Interaktive Shells haben die Shelloption i gesetzt. Kann man also
seit vier Jahrzehnten z.B. so
case $- in *i*) echo interactive ;; esac
prüfen. Das funktioniert dann mit beliebigen Shells der
Bourne-Familie, anders als
sh -c 'echo ${PS1-unset}'
$
Ähh, ja. Genau deswegen ja mein "sinnigerweise", und deshalb
| Es wird also nicht etwa auf einen Aufrufparameter geprüft,
| sondern darauf, ob PS1 gesetzt ist, [...]
Ich vermute, der Autor hat es nicht hinbekommen, eine robuste und
lesbare Form, etwa

if ${BASH_VERSION:+:} false &&
case $- in *i*) : ;; *) false ;; esac &&
! ${BASH_COMPLETION_VERSINFO+:} false
then

aufzusetzen.
Michael Ottenbruch
2021-06-02 06:23:59 UTC
Permalink
Post by Helmut Waitzmann
[...]
Post by Michael Ottenbruch
| if [ "x${BASH_VERSION-}" != x -a "x${PS1-}" != x -a "x${BASH_COMPLETION_VERSINFO-}" = x ]; then
Darin, wie man lesbaren und robusten Code schreibt, könnte der Autor
noch etwas Nachhilfe vertragen.
Post by Michael Ottenbruch
, kann es ja eigentlich auch nicht um Kompatibilität mit
irgendwelchen alten bash-Versionen oder gar anderen Shells als der
bash gehen;
Wenn es darum nicht ginge, wäre der Test, ob es die Variable
«BASH_VERSION» gibt und ihr Inhalt nicht leer ist, unnötig.  Da der
Test aber gemacht wird, muss ich daraus schließen, dass dieses Stück
Code auch bei anderen Shells zu einem vernünftigen Ergebnis kommen
soll.
Vielleicht habe ich auch da etwas falsch in Erinnerung, aber ich hatte
geglaubt, es gäbe keine bash-Version, bei der die Variable
«BASH_COMPLETION_VERSINFO» gesetzt ist, «BASH_VERSION» aber nicht. Von
daher hatte ich tatsächlich angenommen, daß "der Test, ob es die
Variable «BASH_VERSION» gibt und ihr Inhalt nicht leer ist, unnötig"
ist, sofern man schon auf «BASH_COMPLETION_VERSINFO» testet.
--
...und tschuess!

Michael
E-mail: ***@sailor.ping.de
Michael Ottenbruch
2021-06-02 07:12:31 UTC
Permalink
Am Wed, 02 Jun 2021 08:23:59 +0200, schrieb Michael "Ingrid" Ottenbruch:

Das war natürlich Blödsinn: Ich hatte übersehen, daß die letzte
Bedingung eine Prüfung auf das NICHT-Vorhandensein von
«BASH_COMPLETION_VERSINFO» ist. Sorry!
Post by Michael Ottenbruch
Post by Helmut Waitzmann
[...]
Post by Michael Ottenbruch
| if [ "x${BASH_VERSION-}" != x -a "x${PS1-}" != x -a "x${BASH_COMPLETION_VERSINFO-}" = x ]; then
Darin, wie man lesbaren und robusten Code schreibt, könnte der Autor
noch etwas Nachhilfe vertragen.
Post by Michael Ottenbruch
, kann es ja eigentlich auch nicht um Kompatibilität mit
irgendwelchen alten bash-Versionen oder gar anderen Shells als der
bash gehen;
Wenn es darum nicht ginge, wäre der Test, ob es die Variable
«BASH_VERSION» gibt und ihr Inhalt nicht leer ist, unnötig.  Da der
Test aber gemacht wird, muss ich daraus schließen, dass dieses Stück
Code auch bei anderen Shells zu einem vernünftigen Ergebnis kommen
soll.
Vielleicht habe ich auch da etwas falsch in Erinnerung, aber ich hatte
geglaubt, es gäbe keine bash-Version, bei der die Variable
«BASH_COMPLETION_VERSINFO» gesetzt ist, «BASH_VERSION» aber nicht. Von
daher hatte ich tatsächlich angenommen, daß "der Test, ob es die
Variable «BASH_VERSION» gibt und ihr Inhalt nicht leer ist, unnötig"
ist, sofern man schon auf «BASH_COMPLETION_VERSINFO» testet.
--
...und tschuess!

Michael
E-mail: ***@sailor.ping.de
j***@schily.net
2021-06-02 14:14:37 UTC
Permalink
Post by Christian Weisgerber
Interaktive Shells haben die Shelloption i gesetzt. Kann man also
seit vier Jahrzehnten z.B. so
case $- in *i*) echo interactive ;; esac
prüfen. Das funktioniert dann mit beliebigen Shells der Bourne-Familie,
anders als
Diese Behauptung ist definitv falsch!

Der Bourne Shell hat niemals -i gesetzt, wenn er im interaktiven Modus war.

Die Option -i war immer eigentlich nur dazu da, den interaktiven Modus von
Außen zu erzwingen, wenn der Shell von sich aus nicht interaktiv wäre.

Die offizielle Methode auf einen interaktiven Shell zu prüfen war immer das
Vorhandensein von PS1 zu prüfen, da man üblicherweise PS1 nicht exportiert
hat.

Der Bourne Shell hat allerdings das "ttyflg" gesetzt wenn der Input ein TTY war
und man daher "interaktiv" angenommen hat. Allerdings ist "ttyflg" nicht einer
außen setzbaren oder über $- abfragbaren Option zugeordnet.

Also: Das was Du da beschrieben hast, wurde entweder mit ksh88 oder mit POSIX
1992 eingeführt.

Aktuelle Versionen vom Bourne Shell setzen allerdings (wenn sie nicht für
Kompatibilität mit Früher kompiliert wurden) -i im interaktiven Modus
automatisch, weil ich den Bourne Shell vor 4 Jahren POSIX Kompatibel erweitert
habe.

Wenn man auf Solaris 10 oder älter ist, oder wenn man sich auf einem anderen
System befindet, bei dem /bin/sh kein POSIX Shell ist, ist Deine Behauptung mit
großer Vorsicht zu genießen. POSIX verlangt nämlich keinesfalls, daß /bin/sh
ein POSIX kompatibler Shell ist, sondern lediglich, daß man mit:

PATH=`getconf PATH`
export PATH
sh

einen POSIX kompatiblen Shell bekommen kann.
--
EMail:***@schily.net Jörg Schilling D-13353 Berlin
Blog: http://schily.blogspot.com/
URL: http://cdrecord.org/private/ http://sourceforge.net/projects/schilytools/files/
Marcel Logen
2021-05-30 14:56:15 UTC
Permalink
Post by fritz_s
do
read -p ..... VER
[[ $VER == *(+([0-9])\.)+([0-9]) ]] && break
echo Nö
done
HTH
Das schon, aber warum das gleiche nicht auch mit case geht, würde mich
Inzwischen hatte ich mich noch gefragt, warum es denn inner-
halb von [[ ... ]] ohne shopt funktioniert.

Das liegt hierin begründet (man bash):

| Compound Commands
|
| A compound command is one of the following. [...]
|
| [[ expression ]]
| Return a status of 0 or 1 depending on the
| evaluation of the conditional expression
| expression. [...]
|
| When the == and != operators are used, the string to the
| right of the operator is considered a pattern and matched
| according to the rules described below under Pattern Mat-
| ching, as if the extglob shell option were enabled. [...]

Marcel
--
╭───╮ ╭─╮ ╭─╮ ╭──╮ ╭─╮
│ ╰─╯ ╰─╮ │ ╰─────╮ ╭──────╯ ╰──╯ │
──╮ ╭─╮ ╭─╯ ╭─╯ ╭──╮ ╭─╮ ╭─╯ ╭─╯ ╭─╮ ╭──╯ ╰
╰─╯ ╰─╯ ╰────╯ ╰───╯ ╰──╯ ╰────╯ ╰──╯ 15b483
Christian Weisgerber
2021-05-29 15:28:20 UTC
Permalink
Post by Michael Ottenbruch
Post by Detlef Paschke
case $VER in
[0-9]* ) echo "Versionsnummer: $VER"; break;;
* ) echo "Keine gültige Versionsnummer";;
esac
Ich hätte gedacht, daß das im letzten Satz Beschriebene äußerst simpel
durch das vergleichsmuster "[0-9\.]*" zu erreichen wäre, da ja der
Backslash die Sonderbedeutung des folgenden Zeichens ("The period .
matches any single character.") aufheben soll.
[...]
Ich kann Dir also leider nicht weiterhelfen, wäre aber sehr dankbar,
wenn mir jemand meine Denkfehler erklären könnte.
case verwendet Globs (Shell Patterns), keine Regular Expressions.
--
Christian "naddy" Weisgerber ***@mips.inka.de
Juergen Ilse
2021-06-03 06:38:26 UTC
Permalink
Hallo,
Post by Detlef Paschke
Im betreffenden Script soll eine Versionsnummer abgefragt werden, welche
aus einer unbekannten Anzahl von Zahlen und ebenso unbekannt vielen
Punkten bestehen kann. (NN.NN.NN)
Was ich bis dato zusammenbekommen habe, prüft zumindest erst mal darauf,
dass das erste Zeichen eine Zahl ist. Die Eingabe 1.8.3 geht als
Versionsnummer durch, Programm-1.8.3 würde "raus fliegen".
#!/bin/bash
while true; do
read -p "$(echo -e '\033[32m'Versionsnummer angeben.'\033[0m') " VER
case $VER in
[0-9]* ) echo "Versionsnummer: $VER"; break;;
* ) echo "Keine gültige Versionsnummer";;
esac
done
Ein wesentlicher Teil von Programmierung (das trifft auch auf das script
schreiben zu) ist es, sich *genau* zu ueberlegen, was man denn eigentlich
erreichen moechte. Wie sieht genau denn der string aus, den du als
"gueltige Versionsnummer" akzeptierst. Aus deiner Beschreibung wuerde
ich jetzt mal die folgenden Eigenschaften vermuten:

1. beginnt nicht mit einem "."
2. endet nicht mit einem "."
3. enthaelt keine 2 direkt aufeinander folgende "."
4. enthaelt keine Zeichen ausser Dezimalziffern und dem "."

Wie waere es da, zuerst auf diese 4 Eigenschaften zu pruefen, die
*keine* gueltige Versionsnummer darstellen, und alles andere muss
dann ja wohl eine gueltige Versionsnummer sein.

case $VER in
.*) echo "Keine gültige Versionsnummer";;
*.) echo "Keine gültige Versionsnummer";;
*..*) echo "Keine gültige Versionsnummer";;
*[!0-9.]*) echo "keine gültige Versionsnummer";;
*) echo "Versionsnummer: $VER";;
esac

Erfuellt das nicht den von dir angestrebten Zweck? Eine andere Moeglichkeit
waere es evt. (z.B. mittels "grep") "$VER" gegen eine "regular expression"
wie "^\([0-9]*[0-9]\.\)*[0-9]*[0-9]" zu matchen (bei Verwendung von egrep
und "extended regular expressions" koennte man den Ausdruck noch etwas
verkuerzen), aber ich wuerde hier evt. obenstehende Version mit "case"
vorzuziehen ...

Tschuess,
Juergen Ilse (***@usenet-verwaltung.de)
Michael Ottenbruch
2021-06-03 08:22:55 UTC
Permalink
Post by Juergen Ilse
Hallo,
Post by Detlef Paschke
Im betreffenden Script soll eine Versionsnummer abgefragt werden, welche
aus einer unbekannten Anzahl von Zahlen und ebenso unbekannt vielen
Punkten bestehen kann. (NN.NN.NN)
Was ich bis dato zusammenbekommen habe, prüft zumindest erst mal darauf,
dass das erste Zeichen eine Zahl ist. Die Eingabe 1.8.3 geht als
Versionsnummer durch, Programm-1.8.3 würde "raus fliegen".
#!/bin/bash
while true; do
read -p "$(echo -e '\033[32m'Versionsnummer angeben.'\033[0m') " VER
case $VER in
[0-9]* ) echo "Versionsnummer: $VER"; break;;
* ) echo "Keine gültige Versionsnummer";;
esac
done
Ein wesentlicher Teil von Programmierung (das trifft auch auf das script
schreiben zu) ist es, sich *genau* zu ueberlegen, was man denn eigentlich
erreichen moechte. Wie sieht genau denn der string aus, den du als
"gueltige Versionsnummer" akzeptierst. Aus deiner Beschreibung wuerde
1. beginnt nicht mit einem "."
2. endet nicht mit einem "."
3. enthaelt keine 2 direkt aufeinander folgende "."
4. enthaelt keine Zeichen ausser Dezimalziffern und dem "."
Wie waere es da, zuerst auf diese 4 Eigenschaften zu pruefen, die
*keine* gueltige Versionsnummer darstellen, und alles andere muss
dann ja wohl eine gueltige Versionsnummer sein.
case $VER in
.*) echo "Keine gültige Versionsnummer";;
*.) echo "Keine gültige Versionsnummer";;
*..*) echo "Keine gültige Versionsnummer";;
*[!0-9.]*) echo "keine gültige Versionsnummer";;
*) echo "Versionsnummer: $VER";;
esac
Erfuellt das nicht den von dir angestrebten Zweck? Eine andere Moeglichkeit
waere es evt. (z.B. mittels "grep") "$VER" gegen eine "regular expression"
wie "^\([0-9]*[0-9]\.\)*[0-9]*[0-9]" zu matchen (bei Verwendung von egrep
und "extended regular expressions" koennte man den Ausdruck noch etwas
verkuerzen), aber ich wuerde hier evt. obenstehende Version mit "case"
vorzuziehen ...
Was spricht denn gegen die in <s8tv6p$ujk$***@lucy.ping.de> vorgeschlagene
variante:

| while :
| do
| read -p ..... VER
| [[ $VER == *(+([0-9])\.)+([0-9]) ]] && break
| echo Nö
| done

bzw. mit gesetztem

| shopt -s extglob

die Variante:

| case $VER in
| *(+([0-9])\.)+([0-9]) ) echo "Versionsnummer: $VER"; break;;
| * ) echo "Keine gültige Versionsnummer";;
| esac

?

Das prüft auf null- oder mehrmaliges Auftreten von einer oder mehreren
Ziffern gefolgt von genau einem Punkt, und das gefolgt von einer oder
mehreren Ziffern. Das sollte doch die o.g. Kriterien erfüllen.

Und es ist IMHO als eine Positiv-Definition leichter verständlich als
durch vier Negativ-Definitionen.
--
...und tschuess!

Michael
E-mail: ***@sailor.ping.de
Detlef Paschke
2021-06-05 14:06:07 UTC
Permalink
Am 03.06.2021 um 10:22 schrieb Michael Ottenbruch:

Hallo in die Rund,

zunächst bedanke ich mich bei allen für die rege Beteiligung und
entschuldige mich auch gleich für meine späte Antwort.
Wie es jedoch zu dieser Jahreszeit ist, hat man auf einem alten Gehöft
schon allein mit der Mahd eine menge Arbeit.
Post by Michael Ottenbruch
Post by Juergen Ilse
Ein wesentlicher Teil von Programmierung (das trifft auch auf das script
schreiben zu) ist es, sich *genau* zu ueberlegen, was man denn eigentlich
erreichen moechte. Wie sieht genau denn der string aus, den du als
"gueltige Versionsnummer" akzeptierst. Aus deiner Beschreibung wuerde
Ich war der Meinung, dass ich es recht genau in meiner Fragestellung
beschrieben hatte. "Im betreffenden Script soll eine Versionsnummer
abgefragt werden, welche aus einer unbekannten Anzahl von Zahlen und
ebenso unbekannt vielen Punkten bestehen kann. (NN.NN.NN)". Die Angabe
"N" sollte eine Zahl interpretieren.

Die derzeit aktuelle Versionsnummer des jetzt betroffenen Programm lt.
6.0.0 doch diese wird sich im Lauf der Zeit natürlich nach oben verändern.

Erreichen möchte ich, dass man nach der Abfrage nach der Versionsnummer
eine Fehlermeldung bekommt, sollte man wie in diesem Beispiel
"Programm-6.0.0" eingeben, jedoch keine, wenn man "6.0.0" eingibt.

Das ganze ist ein Script. welches den Sourcecode eines Programm aus dem
Internet lädt und das Programm anschließend kompiliert.

Bei meinem derzeitigen Script funktioniert es im Grunde schon so wie ich
es im Eingang beschrieben habe, weil darauf geprüft wird, dass die
eingegebene Versionsnummer mit einer Zahl beginnt.

Mein Gedanke war, dieses Script später evtl. auch für andere Programme
zu benutzen. Ein schnelles Beispiel wäre 7zip und da würde meine Abfrage
versagen, weil natürlich eine Zahl an erster Stelle steht.

Das ist alles sehr weit hergeholt aber es ging mir darum, ob ich die
Prüfung möglichst einfach etwas Präzisieren könnte, so das nur auf
Zahlen und Punkte geprüft wird.
Post by Michael Ottenbruch
Post by Juergen Ilse
Wie waere es da, zuerst auf diese 4 Eigenschaften zu pruefen, die
*keine* gueltige Versionsnummer darstellen, und alles andere muss
dann ja wohl eine gueltige Versionsnummer sein.
case $VER in
.*) echo "Keine gültige Versionsnummer";;
*.) echo "Keine gültige Versionsnummer";;
*..*) echo "Keine gültige Versionsnummer";;
*[!0-9.]*) echo "keine gültige Versionsnummer";;
*) echo "Versionsnummer: $VER";;
esac
Erfuellt das nicht den von dir angestrebten Zweck? ...
Über den Negativ Ausschluss oder wie man es nenne will zu gehen ist
sicher auch eine Möglichkeit, bläst das ganze Script aber auch wieder
auf was ich immer zu vermeiden versuche. Auf der anderen Seite sehe auch
ich als nicht Script Profi in jeder Zeile ganz genau auf was geprüft
wird. Klassische Zwickmühle. ;-)

Ich habe es jetzt noch nicht versucht aber wenn ich die Zeile in meinem
Script so einsetze,

*[0-9.]*) echo "Versionsnummer: $VER"; break;;

könnte es doch auch schon besser sein oder?
Dann hätte in meiner Zeile ein * zu Beginn gefehlt um auszusagen, dass
ausschließlich Zahlen erlaubt sind?
Nur noch einmal für mein Verständnis. Die Angabe [0-9] bedeutet Zahlen
im allgemeinen also auch mehrstellige?
Post by Michael Ottenbruch
| do
| read -p ..... VER
| [[ $VER == *(+([0-9])\.)+([0-9]) ]] && break
| echo Nö
| done
bzw. mit gesetztem
| shopt -s extglob
| case $VER in
| *(+([0-9])\.)+([0-9]) ) echo "Versionsnummer: $VER"; break;;
| * ) echo "Keine gültige Versionsnummer";;
| esac
Das sind die zwei Varianten, die ich zunächst ins Auge gefasst hatte.
Wenn ich es richtig verstehe, wird geprüft auf eine Zahl, einen Punkt
und eine weitere Zahl? Auch hier noch einmal die Frage, ein- oder
mehrstellige Zahl ist bei der Prüfung bedeutungslos?
Aus Neugierde, was sagt überhaupt das erste + also dieses *(+([0-9... in
der Zeile aus.
Bei diesem extglobe weiß ich zwar noch gar nicht, was das ist und was
ich dafür machen muss doch das findet sich auch noch wenn ich es
benötigen werde.

Viele Grüße
Detlef Paschke
--
Das "Zitat des Augenblicks" gibt es nur auf
http://schabau.eu
Meine "Merkzettel"
http://helpdesk.schabau.eu
Michael Ottenbruch
2021-06-05 15:17:31 UTC
Permalink
Post by Detlef Paschke
Hallo in die Rund,
zunächst bedanke ich mich bei allen für die rege Beteiligung und
entschuldige mich auch gleich für meine späte Antwort.
Wie es jedoch zu dieser Jahreszeit ist, hat man auf einem alten Gehöft
schon allein mit der Mahd eine menge Arbeit.
Post by Michael Ottenbruch
Post by Juergen Ilse
Ein wesentlicher Teil von Programmierung (das trifft auch auf das script
schreiben zu) ist es, sich *genau* zu ueberlegen, was man denn eigentlich
erreichen moechte. Wie sieht genau denn der string aus, den du als
"gueltige Versionsnummer" akzeptierst. Aus deiner Beschreibung wuerde
Ich war der Meinung, dass ich es recht genau in meiner Fragestellung
beschrieben hatte. "Im betreffenden Script soll eine Versionsnummer
abgefragt werden, welche aus einer unbekannten Anzahl von Zahlen und
ebenso unbekannt vielen Punkten bestehen kann. (NN.NN.NN)". Die Angabe
"N" sollte eine Zahl interpretieren.
Das war in der Tat Deine Problembeschreibung; sie erschien AFAICS uns
allen aber nicht umfassend genug. Dies deshalb, weil Versionsnummern
eben nicht nur "aus einer unbekannten Anzahl von Zahlen und ebenso
unbekannt vielen Punkten bestehen". Es handelt sich vielmehr um
wohldefinierte Zeichenfolgen, die in der Regel mindestens aus einer oder
mehreren Ziffern, mglw. gefolgt von genau einem Punkt, dem dann wieder
eine oder mehrere Ziffern folgen können. Diese durch jeweils genau einen
Punkt voneinander getrennten Blöcke von einer oder mehreren Ziffen
können auch mehr als zweimal auftreten.

Darauf prüfen die vorgeschlagenen Ausdrücke.
Post by Detlef Paschke
[...]
Das ist alles sehr weit hergeholt aber es ging mir darum, ob ich die
Prüfung möglichst einfach etwas Präzisieren könnte, so das nur auf
Zahlen und Punkte geprüft wird.
Wenn Du wirklich willst, daß "nur auf Zahlen und Punkte geprüft wird",
nicht aber darauf, ob die Zahlen und Punkte auch eine gültige
Versionsnummer bilden, dann ist das Suchmuster: "[0-9.]" Das ist eine
verkürzte Darstellung von "[0123456789.]", prüft also darauf, ob es sich
bei dem Muster um ein Zeichen handelt, das sich zwischen den eckigen
Klammern findet.
Post by Detlef Paschke
[...]
Ich habe es jetzt noch nicht versucht aber wenn ich die Zeile in meinem
Script so einsetze,
*[0-9.]*) echo "Versionsnummer: $VER"; break;;
könnte es doch auch schon besser sein oder?
Nein, denn der Asterisk ("*") prüft auf null- bis beliebig viele
beliebige Zeichen, Dein Vorschlag ("*[0-9.]*") also darauf, ob innerhalb
beliebiger Zeichen auch mindestens eine Ziffer oder ein Punkt vorkommt.

Das ist - so weit ich Dich verstanden habe - nicht das, was Du möchtest.
Post by Detlef Paschke
Dann hätte in meiner Zeile ein * zu Beginn gefehlt um auszusagen, dass
ausschließlich Zahlen erlaubt sind?
Nur noch einmal für mein Verständnis. Die Angabe [0-9] bedeutet Zahlen
im allgemeinen also auch mehrstellige?
Das Muster "[0-9]" bedeutet genau eine Ziffer.

Eine (natürliche) Zahl ist eine Zeichenfolge, die aus einer oder
mehreren Ziffern besteht. Es gibt auch Zahlen, in denen außerdem noch
Dezimaltrenner vorkommen, je nach Sprache Punkt (".") oder Komma (",").
Post by Detlef Paschke
Post by Michael Ottenbruch
| do
| read -p ..... VER
| [[ $VER == *(+([0-9])\.)+([0-9]) ]] && break
| echo Nö
| done
bzw. mit gesetztem
| shopt -s extglob
| case $VER in
| *(+([0-9])\.)+([0-9]) ) echo "Versionsnummer: $VER"; break;;
| * ) echo "Keine gültige Versionsnummer";;
| esac
Das sind die zwei Varianten, die ich zunächst ins Auge gefasst hatte.
Wenn ich es richtig verstehe, wird geprüft auf eine Zahl, einen Punkt
und eine weitere Zahl? Auch hier noch einmal die Frage, ein- oder
mehrstellige Zahl ist bei der Prüfung bedeutungslos?
Ich hatte dabei geschrieben, worauf das prüft:

| | Das prüft auf null- oder mehrmaliges Auftreten von einer oder mehreren
| | Ziffern gefolgt von genau einem Punkt, und das gefolgt von einer oder
| | mehreren Ziffern. Das sollte doch die o.g. Kriterien erfüllen.
Post by Detlef Paschke
Aus Neugierde, was sagt überhaupt das erste + also dieses *(+([0-9... in
der Zeile aus.
Das erklärt sich wie folgt:

"[0-9]" prüft auf genau eine Ziffer
"+([0-9])" prüft auf ein- oder mehrmaliges Auftreten genau einer
Ziffer - das "+" vor der Klammer steht also für "ein-
oder mehrmals"
"+([0-9])\." prüft auf ein- oder mehrmaliges Auftreten genau einer
Ziffer gefolgt von genau einem Punkt. (Ohne den
Backslash stünde der Punkt für genau ein beliebiges
Zeichen. Der Backslash hebt diese Sonderbedeutung auf,
so daß "\." auf genau einen Punkt prüft.)[1]
"*(+([0-9])\.)" prüft auf null-, ein- oder mehrmaliges Auftreten der
letztgenannten Zeichenfolge - der "*" vor der Klammer
steht also für "null-, ein- oder mehrmals"

Das Ganze bis hierhin paßt also auch auf eine leere Zeichenkette (wegen
des "*", der ja auch für nullmaliges Auftreten stehen kann). Danach wird
dann aber nochmals mit "+([0-9])" auf auf ein- oder mehrmaliges
Auftreten genau einer Ziffer geprüft. Mindestens ein Ziffernstring muß
also da sein.
Post by Detlef Paschke
Bei diesem extglobe weiß ich zwar noch gar nicht, was das ist und was
ich dafür machen muss doch das findet sich auch noch wenn ich es
benötigen werde.
Es gibt innerhalb der shell mehrere Arten von Mustervergleichen, unter
anderem "globs" (AFAIR steht das für "global expressions"), "extended
globs", und unterschiedliche Arten von so genannten "regular
expressions".

Durch Eingabe von "man bash" erhältst Du eine Anleitung für die Bash.

Wenn Du dort nach "Pattern Matching" suchst, wird Dir erläutert, wie
einfache globs funktionieren. Direkt anschließend wird erläutert, daß
durch Setzen der in der Diskussion hinreichend durchgehechelten
Shell-Option extglob die Funktionsweise der Globs erweitert wird, und
auch, in welcher Weise.

Durch Eingabe von "man grep" erhältst Du eine Anleitung für das Tool
grep, in der Du nach "regular expressions" suchen kannst, die wesentlich
mächtiger sind als Globs und ExtGlobs.

[1] Das stimmt gar nicht: In globs steht das Fragezeichen ("?") für
genau ein beliebiges Zeichen; jedoch steht in regular expressions der
Punkt (".") für genau ein beliebiges Zeichen, was nach einigen Jahren
dazu führt, daß Du reflexartig jeden Punkt "quotest" (also durch einen
vorangestllten Backslash eine etwaige Sonderbedeutung aufhebst), wenn Du
tatsächlich einen Punkt meinst. Schaden kann das Quoten nie. Hier wäre
es nicht nötig gewesen.
--
...und tschuess!

Michael
E-mail: ***@sailor.ping.de
Juergen Ilse
2021-06-05 22:08:08 UTC
Permalink
Hallo,
Post by Michael Ottenbruch
| | Das prüft auf null- oder mehrmaliges Auftreten von einer oder mehreren
| | Ziffern gefolgt von genau einem Punkt, und das gefolgt von einer oder
| | mehreren Ziffern. Das sollte doch die o.g. Kriterien erfüllen.
Post by Detlef Paschke
Aus Neugierde, was sagt überhaupt das erste + also dieses *(+([0-9... in
der Zeile aus.
"[0-9]" prüft auf genau eine Ziffer
"+([0-9])" prüft auf ein- oder mehrmaliges Auftreten genau einer
Ziffer - das "+" vor der Klammer steht also für "ein-
oder mehrmals"
"+([0-9])\." prüft auf ein- oder mehrmaliges Auftreten genau einer
Ziffer gefolgt von genau einem Punkt. (Ohne den
Backslash stünde der Punkt für genau ein beliebiges
Zeichen. Der Backslash hebt diese Sonderbedeutung auf,
so daß "\." auf genau einen Punkt prüft.)[1]
"*(+([0-9])\.)" prüft auf null-, ein- oder mehrmaliges Auftreten der
letztgenannten Zeichenfolge - der "*" vor der Klammer
steht also für "null-, ein- oder mehrmals"
Ist das bei den seltsamen "shell regular expressions" so?
Bei den regular expressions wie in grep, awk, sed, ... muss das "+"
(mindestens einmal, ggfs. auch mehrfach) oder "*" (0 mal oder oefter)
*hinter* der jeweiligen subexpression stehen und nicht davor ...
Post by Michael Ottenbruch
[1] Das stimmt gar nicht: In globs steht das Fragezeichen ("?") für
genau ein beliebiges Zeichen; jedoch steht in regular expressions der
Punkt (".") für genau ein beliebiges Zeichen, was nach einigen Jahren
dazu führt, daß Du reflexartig jeden Punkt "quotest" (also durch einen
vorangestllten Backslash eine etwaige Sonderbedeutung aufhebst), wenn Du
tatsächlich einen Punkt meinst. Schaden kann das Quoten nie. Hier wäre
es nicht nötig gewesen.
Ich quote Punkte nur in regular expressions, aber nie in shell wildcards.
Ich bin uch nie irgendwann in Versuchung gekommen, Punkte quoten zu wollen,
daich mir immer im klaren darueber bin, ob ich gerade mit shell wildcards
oder regular expressions arbeite.

Tschuess,
Juergen Ilse (***@usenet-verwaltung.de)
Michael Ottenbruch
2021-06-06 03:46:01 UTC
Permalink
Post by Juergen Ilse
Hallo,
Post by Michael Ottenbruch
| | Das prüft auf null- oder mehrmaliges Auftreten von einer oder mehreren
| | Ziffern gefolgt von genau einem Punkt, und das gefolgt von einer oder
| | mehreren Ziffern. Das sollte doch die o.g. Kriterien erfüllen.
Post by Detlef Paschke
Aus Neugierde, was sagt überhaupt das erste + also dieses *(+([0-9... in
der Zeile aus.
"[0-9]" prüft auf genau eine Ziffer
"+([0-9])" prüft auf ein- oder mehrmaliges Auftreten genau einer
Ziffer - das "+" vor der Klammer steht also für "ein-
oder mehrmals"
"+([0-9])\." prüft auf ein- oder mehrmaliges Auftreten genau einer
Ziffer gefolgt von genau einem Punkt. (Ohne den
Backslash stünde der Punkt für genau ein beliebiges
Zeichen. Der Backslash hebt diese Sonderbedeutung auf,
so daß "\." auf genau einen Punkt prüft.)[1]
"*(+([0-9])\.)" prüft auf null-, ein- oder mehrmaliges Auftreten der
letztgenannten Zeichenfolge - der "*" vor der Klammer
steht also für "null-, ein- oder mehrmals"
Ist das bei den seltsamen "shell regular expressions" so?
Bei den regular expressions wie in grep, awk, sed, ... muss das "+"
(mindestens einmal, ggfs. auch mehrfach) oder "*" (0 mal oder oefter)
*hinter* der jeweiligen subexpression stehen und nicht davor ...
Ja, das ist bei den seltsamen "shell regular expressions" so:

| If the extglob shell option is enabled using the shopt builtin, several extended pattern matching operators
| are recognized. In the following description, a pattern-list is a list of one or more patterns separated by a
| |. Composite patterns may be formed using one or more of the following sub-patterns:
|
| ?(pattern-list)
| Matches zero or one occurrence of the given patterns
| *(pattern-list)
| Matches zero or more occurrences of the given patterns
| +(pattern-list)
| Matches one or more occurrences of the given patterns
| @(pattern-list)
| Matches one of the given patterns
| !(pattern-list)
| Matches anything except one of the given patterns
Post by Juergen Ilse
Post by Michael Ottenbruch
[1] Das stimmt gar nicht: In globs steht das Fragezeichen ("?") für
genau ein beliebiges Zeichen; jedoch steht in regular expressions der
Punkt (".") für genau ein beliebiges Zeichen, was nach einigen Jahren
dazu führt, daß Du reflexartig jeden Punkt "quotest" (also durch einen
vorangestllten Backslash eine etwaige Sonderbedeutung aufhebst), wenn Du
tatsächlich einen Punkt meinst. Schaden kann das Quoten nie. Hier wäre
es nicht nötig gewesen.
Ich quote Punkte nur in regular expressions, aber nie in shell wildcards.
Ich bin uch nie irgendwann in Versuchung gekommen, Punkte quoten zu wollen,
Bei RegExps bin ich schon oft in diese Versuchung gekommen - fast
jedesmal, wenn ich tatsächlich einen Punkt gemeint habe.
Post by Juergen Ilse
daich mir immer im klaren darueber bin, ob ich gerade mit shell wildcards
oder regular expressions arbeite.
Ich mache das nicht beruflich. ;-\ Ich bin mir sicher, daß ich die
Gelegenheiten, bei denen ich in den letzten 20 Jahren mit extglobs
gearbeitet habe, an den Fingern einer Hand abzählen kann; und
wahrscheinlich habe ich manchmal gar nicht gewußt, warum das, was ich
tue, da funktioniert. Intensiv beschäftigt habe ich mich nur mit
regexps.

Mit den Feinheiten der Shell-Option extglob habe ich mich während der
jetzt laufenden Diskussion zum allerersten Mal beschäftigt.

Aber als mir aufgefallen ist, daß mein Quoting hier überflüssig war,
wollte ich Detlef wenigstens erklären, wie der Backslash ins pattern
gekommen ist.
--
...und tschuess!

Michael
E-mail: ***@sailor.ping.de
Juergen Ilse
2021-06-09 20:45:34 UTC
Permalink
Hallo,
Post by Michael Ottenbruch
| If the extglob shell option is enabled using the shopt builtin, several extended pattern matching operators
| are recognized. In the following description, a pattern-list is a list of one or more patterns separated by a
|
| ?(pattern-list)
| Matches zero or one occurrence of the given patterns
| *(pattern-list)
| Matches zero or more occurrences of the given patterns
| +(pattern-list)
| Matches one or more occurrences of the given patterns
| Matches one of the given patterns
| !(pattern-list)
| Matches anything except one of the given patterns
Danke. Ich habe diesen Kram noch *nie* benutzt, deswegen ist mir das auch
nicht gelaeufig ...
Post by Michael Ottenbruch
Ich mache das nicht beruflich. ;-\ Ich bin mir sicher, daß ich die
Gelegenheiten, bei denen ich in den letzten 20 Jahren mit extglobs
gearbeitet habe, an den Fingern einer Hand abzählen kann; und
wahrscheinlich habe ich manchmal gar nicht gewußt, warum das, was ich
tue, da funktioniert. Intensiv beschäftigt habe ich mich nur mit
regexps.
Mit "extglob" habe ich mich noch nie befasst (ich weiss noch nicht einmal,
welche shells das unterstuetzten und welche vielleicht nicht ...
Mit regexps (sowohl basic als auch extendded) habe ich dagegen oefter zu tun
(aber nicht mit den perl-regexp, da ich bei basic und extended regexp einiger-
massen sicher bin, wo die zu finden sind und ich davon ausgehen kann, bei
perl-regexp jedoch nicht).
Post by Michael Ottenbruch
Mit den Feinheiten der Shell-Option extglob habe ich mich während der
jetzt laufenden Diskussion zum allerersten Mal beschäftigt.
Ich habe mich damit *noch* *nie* beschaeftigt, weil ich es nie gebraucht
habe, und ich mir da nie so sicher war, bei welchen shells ausserhalb des
bash-Umfelds ich mich darauf verlassen kann ...

Ich wuerde nach wie vor zur Loesung des Problems meinen ersten Vorschlag
(mit den 5 "case" Zweigen) bevorzugen. Sie ist klar verstaendlich, und
benoetigt weder "umsetzen von shopts" noch "externe Kommandos".

Tschuess,
Juergen Ilse (***@usenet-verwaltung.de)
Juergen Ilse
2021-06-05 21:56:24 UTC
Permalink
Hallo,
Post by Detlef Paschke
Post by Michael Ottenbruch
Post by Juergen Ilse
Wie waere es da, zuerst auf diese 4 Eigenschaften zu pruefen, die
*keine* gueltige Versionsnummer darstellen, und alles andere muss
dann ja wohl eine gueltige Versionsnummer sein.
case $VER in
.*) echo "Keine gültige Versionsnummer";;
*.) echo "Keine gültige Versionsnummer";;
*..*) echo "Keine gültige Versionsnummer";;
*[!0-9.]*) echo "keine gültige Versionsnummer";;
*) echo "Versionsnummer: $VER";;
esac
Erfuellt das nicht den von dir angestrebten Zweck? ...
Über den Negativ Ausschluss oder wie man es nenne will zu gehen ist
sicher auch eine Möglichkeit, bläst das ganze Script aber auch wieder
auf was ich immer zu vermeiden versuche.
4 zusaetzliche scriptzeilen sind fuer die Bloat? Wenn ja, wuerde ich dir
empfehlen, eine andere Sprache zu verwenden.
Post by Detlef Paschke
Auf der anderen Seite sehe auch
ich als nicht Script Profi in jeder Zeile ganz genau auf was geprüft
wird. Klassische Zwickmühle. ;-)
Ich habe es jetzt noch nicht versucht aber wenn ich die Zeile in meinem
Script so einsetze,
*[0-9.]*) echo "Versionsnummer: $VER"; break;;
könnte es doch auch schon besser sein oder?
Es erfuellt dann immer noch nicht deine Anforderungen (wie ich IIRC
bereits schrieb): mehrere direkt aufeinanderfolgende Punkte werden
genauso wenig abgefangen, wie Punkte am Anfang oder Ende der Eingabe.
Mir erscheint mein Vorschlag als portabel, unabhaengig von der shell
Version (nicht immer und ueberall muss eine bash vorhanden sein), und
ohne Hacks wie Manipulationen wie aendern der "shopts".
Post by Detlef Paschke
Dann hätte in meiner Zeile ein * zu Beginn gefehlt um auszusagen, dass
ausschließlich Zahlen erlaubt sind?
Das was du als "Versionsnummer" abpruefen laesst, laesst sich mittels
"regular expressions" (wie sie grep, awk, sed, ... Verwenden) durchaus
mittels nur eines matches angeben, nicht aber mit "shell wildcards".
Letztere sind dazu einfach nicht maechtig genug.
Post by Detlef Paschke
Nur noch einmal für mein Verständnis. Die Angabe [0-9] bedeutet Zahlen
im allgemeinen also auch mehrstellige?
Nein. Sowohl in shell wildcards als auch in regular expressions matched das
nur *ein* Zeichen aus der angegebenen Liste. Bei regular expressions bewirkt
ein "^" als erstes Zeichen in der Liste, dass die Auswahl "umgekehrt" wird
(der Ausdruck matched dann ein beliebiges Zeichen, dass in der Liste *nicht*
vorkommt). Bei shell wildcards erfuellt "!" diese Funktion (die bash akzep-
tiert statt des "!" auch das von regular expressions bekannte "^", aber das
ist meines Wissens eine Inkompatibilitaet zum POSIX Standard fuer shells.
Da "!" sowohll bei der bash als auch bei anderen "bourne kompatiblen" shells
funktioniert, wuerde ich das vorziehhen (und in der csh sollte man sowieso
nicht scripten ...).
In den 5 Zeilen in meinem Scipt wird also zuerst auf "beginnt mit "." getes-
tet, dann auf "endet mit ".", anschliessend auf "enthaelt 2 "." in Folge,
dann auf "enthaelt Zeichen ausser [0-9.]". All diese Moeglichkeiten bedeu-
ten "keine gueltige Versionsnummer". Alles, was dann noch uebrig bleibt,
muss also eine gueltige Versionsnummer sein (und das ist dann der letzte
Match in meinem Script).
Post by Detlef Paschke
Post by Michael Ottenbruch
| do
| read -p ..... VER
| [[ $VER == *(+([0-9])\.)+([0-9]) ]] && break
| echo Nö
| done
bzw. mit gesetztem
| shopt -s extglob
| case $VER in
| *(+([0-9])\.)+([0-9]) ) echo "Versionsnummer: $VER"; break;;
| * ) echo "Keine gültige Versionsnummer";;
| esac
Das sind die zwei Varianten, die ich zunächst ins Auge gefasst hatte.
Bei der ersten bin ich nicht sicher, ob es nicht eine bash Spezialitaet ist
(die man IMHO wenn moeglich vermekiden sollte), die zweite erfordert ein
herumfummeln an "shopts", die das Verhalten der shell insgesamt aendern und
zu unschoenen Ueberraschungen fuehren kann, wenn der vorherige Zustand nicht
wieder rekonstruiert wird ... Ausserdem bin ich mir da ebenflls nicht sicher,
ob eine einfache Bourne-shell das kann.
Post by Detlef Paschke
Wenn ich es richtig verstehe, wird geprüft auf eine Zahl, einen Punkt
und eine weitere Zahl? Auch hier noch einmal die Frage, ein- oder
mehrstellige Zahl ist bei der Prüfung bedeutungslos?
In Beiden Faellen wird gegen "regular exxpressions" gematched. Dazu hatte
ich auch eine Variante vorgeschlagen, die aber nicht die shell selbst son-
dern ein "externes Kommando" (in dem Fall "grep") dafuer verwendet. Die
Version waere dann aber wieder shell-unabhaengig.
Post by Detlef Paschke
Aus Neugierde, was sagt überhaupt das erste + also dieses *(+([0-9... in
der Zeile aus.
Moeglicherweise fuer das matchen von regexp in der bash erforderlich. Da ich
solche Konstrukte nicht verwende, kann ich es dir nicht genau sagen.
Uebrigens waere es eine gute Idee, "$VER" in doppelte Anfuehrungszeichen zu
setzen, um ein "wod splitting" durch die shell zu vermeiden, fall §VER
whitespace enthalten sollte ... Das waere auch an meinem Vorschlag noch zu
korrigieren.

Tschuess,
Juergen Ilse (***@usenet-verwaltung.de)
Christian Weisgerber
2021-06-06 00:48:11 UTC
Permalink
Post by Juergen Ilse
Post by Michael Ottenbruch
| [[ $VER == *(+([0-9])\.)+([0-9]) ]] && break
| case $VER in
| *(+([0-9])\.)+([0-9]) ) echo "Versionsnummer: $VER"; break;;
| * ) echo "Keine gültige Versionsnummer";;
| esac
Bei der ersten bin ich nicht sicher, ob es nicht eine bash Spezialitaet ist
(die man IMHO wenn moeglich vermekiden sollte), die zweite erfordert ein
herumfummeln an "shopts", die das Verhalten der shell insgesamt aendern und
zu unschoenen Ueberraschungen fuehren kann, wenn der vorherige Zustand nicht
wieder rekonstruiert wird ... Ausserdem bin ich mir da ebenflls nicht sicher,
ob eine einfache Bourne-shell das kann.
Kann sie nicht. Die „extended globs“ und [[ ... ]] sind Korn-Shell-
Erweiterungen, die bash irgendwann übernommen hat. Dass man die
Extended Globs dann noch in manchen Fällen freischalten muss, ist
wiederum bash-spezifisch.
Post by Juergen Ilse
Uebrigens waere es eine gute Idee, "$VER" in doppelte Anfuehrungszeichen zu
setzen, um ein "wod splitting" durch die shell zu vermeiden, fall §VER
whitespace enthalten sollte ... Das waere auch an meinem Vorschlag noch zu
korrigieren.
Beim Wort nach case findet kein Globbing oder Word Splitting statt;
„case $VER in“ ist völlig in Ordnung.

(Bei [[ ... ]] findet auf der linken Seite ebenfalls kein Globbing
oder Word Splitting statt.)
--
Christian "naddy" Weisgerber ***@mips.inka.de
Michael Ottenbruch
2021-06-06 05:58:35 UTC
Permalink
Post by Juergen Ilse
Post by Michael Ottenbruch
| case $VER in
[..]
Uebrigens waere es eine gute Idee, "$VER" in doppelte Anfuehrungszeichen zu
setzen, um ein "wod splitting" durch die shell zu vermeiden, fall §VER
whitespace enthalten sollte ... Das waere auch an meinem Vorschlag noch zu
korrigieren.
So ist das mit dem reflexartigen Quoten: Hier wäre es unnötig, weil -
wie Naddy in <***@lorvorc.mips.inka.de> erklärt hat -
in diesem speziellen Fall ("case"-Verzweigung) kein "word splitting"
stattfindet. Da es aber auch nicht schadet, ist es IMHO kein Fehler,
sich anzugewöhnen, Variablen IMMER zu quoten (oder ${var} zu verwenden,
wobei ich allerdings nicht weiß, ob das nicht auch ein Bashismus ist),
ebensowenig wie bestimmte Zeichen IMMER zu quoten, wenn sie keine
Sonderbedeutung haben sollen.

Ich will mich nicht (mehr) darauf verlassen, daß "ich mir immer im
klaren darueber bin", ob in der konkreten Situation nun auch wirklich
"word splitting" stattfinden oder ein Punkt eine Sonderbedeutung haben
könnte oder sonst etwas.

YMMV
--
...und tschuess!

Michael
E-mail: ***@sailor.ping.de
Helmut Waitzmann
2021-06-06 06:48:11 UTC
Permalink
Post by Juergen Ilse
Post by Michael Ottenbruch
| case $VER in
[..]
Uebrigens waere es eine gute Idee, "$VER" in doppelte
Anfuehrungszeichen zu setzen, um ein "wod splitting" durch die
shell zu vermeiden, fall §VER whitespace enthalten sollte ... Das
waere auch an meinem Vorschlag noch zu korrigieren.
[…]
Da es aber auch nicht schadet, ist es IMHO kein Fehler, sich
anzugewöhnen, Variablen IMMER zu quoten (oder ${var} zu verwenden,
wobei ich allerdings nicht weiß, ob das nicht auch ein Bashismus
ist)
${var} ist kein Bashismus.  POSIX kennt es auch:
<https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02>
Juergen Ilse
2021-06-09 20:59:37 UTC
Permalink
Hallo,
Post by Helmut Waitzmann
Post by Juergen Ilse
Post by Michael Ottenbruch
| case $VER in
[..]
Uebrigens waere es eine gute Idee, "$VER" in doppelte
Anfuehrungszeichen zu setzen, um ein "wod splitting" durch die
shell zu vermeiden, fall §VER whitespace enthalten sollte ... Das
waere auch an meinem Vorschlag noch zu korrigieren.
[…]
Da es aber auch nicht schadet, ist es IMHO kein Fehler, sich
anzugewöhnen, Variablen IMMER zu quoten (oder ${var} zu verwenden,
wobei ich allerdings nicht weiß, ob das nicht auch ein Bashismus
ist)
<https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02>
Ja, aber es quotet nicht,noch nicht einmal in der bash:

***@raspberrypi:~ $ VAR="mit mehr als einem blank in Folge"
***@raspberrypi:~ $ echo $VAR
mit mehr als einem blank in Folge
***@raspberrypi:~ $ echo ${VAR}
mit mehr als einem blank in Folge
***@raspberrypi:~ $ echo "${VAR}"
mit mehr als einem blank in Folge
***@raspberrypi:~ $

Tschuess,
Juergen Ilse (***@usenet-verwaltung.de)
Helmut Waitzmann
2021-06-09 22:56:29 UTC
Permalink
Post by Helmut Waitzmann
Post by Juergen Ilse
Post by Michael Ottenbruch
| case $VER in
[..]
Uebrigens waere es eine gute Idee, "$VER" in doppelte
Anfuehrungszeichen zu setzen, um ein "wod splitting" durch die
shell zu vermeiden, fall §VER whitespace enthalten sollte ... Das
waere auch an meinem Vorschlag noch zu korrigieren.
[…]
Da es aber auch nicht schadet, ist es IMHO kein Fehler, sich
anzugewöhnen, Variablen IMMER zu quoten (oder ${var} zu verwenden,
wobei ich allerdings nicht weiß, ob das nicht auch ein Bashismus
ist)
<https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02>
Ja.  Ich hatte Michaels Aussage «oder ${var} zu verwenden» nicht so
aufgefasst, dass er damit ausdrücken wollte, dass «${var}»
gleichbedeutend mit «"$var"» ist.  Ich vermutete, dass er damit nur
ein weiteres Beispiel für meistens nicht notwendige Maßnahmen geben
wollte – so, wie auch «\.» (außer in regulären Ausdrücken) im Shell
gleichbedeutend mit «.» ist:  Der «\» ist unnötig, schadet aber auch
nicht.  Ich vermutete das auch deshalb, weil er ja selber schrieb,
dass bei «case $var in …» bei der Auswertung von «$var» kein word
splitting erfolgt, die Anführungszeichen also nicht notwendig sind
(aber auch nicht schaden).
Michael Ottenbruch
2021-06-10 08:37:45 UTC
Permalink
Post by Juergen Ilse
Hallo,
Post by Helmut Waitzmann
Post by Juergen Ilse
Post by Michael Ottenbruch
| case $VER in
[..]
Uebrigens waere es eine gute Idee, "$VER" in doppelte
Anfuehrungszeichen zu setzen, um ein "wod splitting" durch die
shell zu vermeiden, fall §VER whitespace enthalten sollte ... Das
waere auch an meinem Vorschlag noch zu korrigieren.
[…]
Da es aber auch nicht schadet, ist es IMHO kein Fehler, sich
anzugewöhnen, Variablen IMMER zu quoten (oder ${var} zu verwenden,
wobei ich allerdings nicht weiß, ob das nicht auch ein Bashismus
ist)
<https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02>
mit mehr als einem blank in Folge
mit mehr als einem blank in Folge
mit mehr als einem blank in Folge
Stimmt. War mißverständlich formuliert.
--
...und tschuess!

Michael
E-mail: ***@sailor.ping.de
j***@schily.net
2021-06-10 18:47:56 UTC
Permalink
Post by Juergen Ilse
Post by Helmut Waitzmann
<https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02>
mit mehr als einem blank in Folge
mit mehr als einem blank in Folge
${VAR} hat ja auch einen anderen Hintergrund. Es geht darum, damit den
Variablen-Namen einzugrenzen.

Also, um z.B. $VARIABLE so auszuzeichnen, daß bei ${VAR}IABLE das VAR
der Variablenname ist und IABLE nicht mehr dazugehört.
Post by Juergen Ilse
mit mehr als einem blank in Folge
Hier könnte man genausogut "$VAR" verwenden.

Nichts davon ist übrigens bash spezifisch. Das ist alles sie Anfang an im
Bourne Shell.
--
EMail:***@schily.net Jörg Schilling D-13353 Berlin
Blog: http://schily.blogspot.com/
URL: http://cdrecord.org/private/ http://sourceforge.net/projects/schilytools/files/
Juergen Ilse
2021-06-15 02:37:50 UTC
Permalink
Hallo,
Post by j***@schily.net
Post by Juergen Ilse
Post by Helmut Waitzmann
<https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02>
mit mehr als einem blank in Folge
mit mehr als einem blank in Folge
${VAR} hat ja auch einen anderen Hintergrund. Es geht darum, damit den
Variablen-Namen einzugrenzen.
Das schrieb ich bereits in einem frueheren Posting. Nur als danach noch
einmal etwas von !quoting" im Zusammenhang mit diesem Konstrukt auftauchte,
hatte ich mich noch einmal zu Wort gemeldet, um klarzustellen, dass dies
*nichts* mit quoting zu tun hat.

Tschuess,
Post by j***@schily.net
Also, um z.B. $VARIABLE so auszuzeichnen, daß bei ${VAR}IABLE das VAR
der Variablenname ist und IABLE nicht mehr dazugehört.
Post by Juergen Ilse
mit mehr als einem blank in Folge
Hier könnte man genausogut "$VAR" verwenden.
Nichts davon ist übrigens bash spezifisch. Das ist alles sie Anfang an im
Bourne Shell.
j***@schily.net
2021-06-06 13:08:53 UTC
Permalink
Post by Michael Ottenbruch
stattfindet. Da es aber auch nicht schadet, ist es IMHO kein Fehler,
sich anzugewöhnen, Variablen IMMER zu quoten (oder ${var} zu verwenden,
wobei ich allerdings nicht weiß, ob das nicht auch ein Bashismus ist),
ebensowenig wie bestimmte Zeichen IMMER zu quoten, wenn sie keine
Sonderbedeutung haben sollen.
Also in den meisten Fällen sollte gequotet werden....

Ansonsten: Mindestens 90% dessen was die Gattung Homo Linuxiensis als
"Baschismus" bezeichnet ist ein kshismus und stammt meist schon vom ksh88, der
mindestens ein Jahr vor dem ersten bash existierte.

Eine verschwindend geringe Anzahl von Features hat David Korn von ksh
übernommen.
--
EMail:***@schily.net Jörg Schilling D-13353 Berlin
Blog: http://schily.blogspot.com/
URL: http://cdrecord.org/private/ http://sourceforge.net/projects/schilytools/files/
Juergen Ilse
2021-06-09 20:54:51 UTC
Permalink
Hallo,
Post by Michael Ottenbruch
Post by Juergen Ilse
Post by Michael Ottenbruch
| case $VER in
[..]
Uebrigens waere es eine gute Idee, "$VER" in doppelte Anfuehrungszeichen zu
setzen, um ein "wod splitting" durch die shell zu vermeiden, fall §VER
whitespace enthalten sollte ... Das waere auch an meinem Vorschlag noch zu
korrigieren.
So ist das mit dem reflexartigen Quoten: Hier wäre es unnötig, weil -
in diesem speziellen Fall ("case"-Verzweigung) kein "word splitting"
stattfindet. Da es aber auch nicht schadet, ist es IMHO kein Fehler,
Das sehe ich auch so.
Post by Michael Ottenbruch
sich anzugewöhnen, Variablen IMMER zu quoten (oder ${var} zu verwenden,
wobei ich allerdings nicht weiß, ob das nicht auch ein Bashismus ist),
${VAR} quotet nichts (zumindest nicht in der bourne shell, vermutlich
auch nicht in anderen shells). Dieses Konstrkt dient einem anderen Zweck:
${VAR}1 haengt an den Inhalt der Variablen VAR die Ziffer 1 an, $VAR1
sucht stattdessen nach dem Inhalt der Vairablen VAR1 (was etwas komplett
anderes ist). ${VAR] gibt es in *jeder* burne-shell kompatiblen shell
einschliesslich der aeltesten mir belkannten bourne shell Versionen.
Post by Michael Ottenbruch
Ich will mich nicht (mehr) darauf verlassen, daß "ich mir immer im
klaren darueber bin", ob in der konkreten Situation nun auch wirklich
"word splitting" stattfinden oder ein Punkt eine Sonderbedeutung haben
könnte oder sonst etwas.
Das ist eine durchaus verstaendliche und sinnvolle Einstellung.
Wenn man unsicher ist, besser einmal mehr quoten.

Tschuess,
Juegen Ilse (***@usenet-verwaltung.de)
Helmut Waitzmann
2021-06-06 02:06:27 UTC
Permalink
Post by Detlef Paschke
Hallo in die Rund,
zunächst bedanke ich mich bei allen für die rege Beteiligung und
entschuldige mich auch gleich für meine späte Antwort.
Keine Sorge.  Das hier ist Usenet, weder Twitter noch WhatsApp. 
Hier ist Qualität wichtiger als bloße Quantität und Schnelligkeit.
Post by Detlef Paschke
Wie es jedoch zu dieser Jahreszeit ist, hat man auf einem alten
Gehöft schon allein mit der Mahd eine menge Arbeit.
Post by Michael Ottenbruch
Post by Juergen Ilse
Ein wesentlicher Teil von Programmierung (das trifft auch auf
das script schreiben zu) ist es, sich *genau* zu ueberlegen, was
man denn eigentlich erreichen moechte. Wie sieht genau denn der
string aus, den du als "gueltige Versionsnummer" akzeptierst.
Aus deiner Beschreibung wuerde ich jetzt mal die folgenden
Ich war der Meinung, dass ich es recht genau in meiner Fragestellung
beschrieben hatte. "Im betreffenden Script soll eine Versionsnummer
abgefragt werden, welche aus einer unbekannten Anzahl von Zahlen und
ebenso unbekannt vielen Punkten bestehen kann. (NN.NN.NN)". Die Angabe
"N" sollte eine Zahl interpretieren.
Da fangen die Schwierigkeiten schon an:  Wenn «N» für eine Zahl,
also vermutlich eine Ziffernfolge, steht, wofür steht dann «NN»? 
Für zwei aneinander geklebte Ziffernfolgen, demnach also eine
mindestens zweistellige Zahl?  Da hättest Du doch sicher «‹N› soll
eine zwei‐ oder mehrstellige Zahl sein» geschrieben, anstelle zwei
mindestens einstellige Zahlen aneinanderzukleben, nicht?  Also wird
der mitdenkende Leser schließen:  Ah, er verwechselt den Begriff
Zahl mit dem Begriff Ziffer.  Also meint er, dass «N» für eine
Ziffer steht.  Damit meint folgerichtig das Muster «NN.NN.NN» also
drei zweistellige Zahlen, mit je einem Punkt verbunden.  Und wo hat
jetzt die unbekannte Anzahl noch Platz?

Das hat jetzt mit der Frage «Wie kriege ich einen entsprechenden
Test ins Skript rein?» noch gar nichts zu tun.  Es scheitert bereits
daran, genau zu beschreiben, wie Versionsnummern aussehen sollen. 
Und das scheitert bereits daran, dass Du in der Beschreibung
zwischen Ziffern und Zahlen nicht sorgfältig unterscheidest.

Ich geb' zu, dass das, obwohl man beim Programmieren noch gar nicht
angekommen ist, bereits Informatik oder diskrete Mathematik ist. 
Aber so ganz scheint das für Dich kein Buch mit sieben Siegeln zu
Post by Detlef Paschke
Nur noch einmal für mein Verständnis. Die Angabe [0-9] bedeutet
Zahlen im allgemeinen also auch mehrstellige?
Nein.  Auf das Muster passt ein einzelnes Zeichen, das eine 0 oder
eine 9 ist oder in der Zeichensortierreihenfolge zwischen 0 und 9
liegt.  Die Sortierreihenfolge hängt vom eingestellen Locale ab. 
Häufig liegen zwischen 0 und 9 nur die Ziffern 1 bis 8.  Dann passt
das Muster «[0-9]» auf genau eine Ziffer, auf sonst nichts. 

Für das Locale «C» ist im POSIX‐Standard festgelegt, dass zwischen
den Ziffern 0 und 9 nur die Ziffern 1 bis 8 liegen.  Man könnte
daher die Sortierreihenfolge mit Hilfe des Locales «C» festklopfen –
das kann allerdings viel Aufwand machen – oder einfach alle Ziffern
aufzählen, indem man «[0123456789]» schreibt.  Das meint unabhängig
vom eingestellten Locale immer genau die (arabischen) Ziffern von 0
bis 9.
Post by Detlef Paschke
Erreichen möchte ich, dass man nach der Abfrage nach der
Versionsnummer eine Fehlermeldung bekommt, sollte man wie in diesem
Beispiel "Programm-6.0.0" eingeben, jedoch keine, wenn man "6.0.0"
eingibt.
[…]
Post by Detlef Paschke
Bei meinem derzeitigen Script funktioniert es im Grunde schon so
wie ich es im Eingang beschrieben habe, weil darauf geprüft wird,
dass die eingegebene Versionsnummer mit einer Zahl beginnt.
Das heißt, dass es nicht alle ungültigen Versionsnummern entdeckt.
Post by Detlef Paschke
Mein Gedanke war, dieses Script später evtl. auch für andere
Programme zu benutzen. Ein schnelles Beispiel wäre 7zip und da
würde meine Abfrage versagen, weil natürlich eine Zahl an erster
Stelle steht.
Genau.
Post by Detlef Paschke
Das ist alles sehr weit hergeholt
Überhaupt nicht.  Das ist der übliche Weg:  Man entwickelt etwas und
merkt, dass man das gerne in Zukunft wiederverwenden will – wer will
schon jedes Mal aufs Neue das Rad erfinden?
Post by Detlef Paschke
aber es ging mir darum, ob ich die Prüfung möglichst einfach etwas
Präzisieren könnte, so das nur auf Zahlen und Punkte geprüft wird.
Post by Michael Ottenbruch
Post by Juergen Ilse
Wie waere es da, zuerst auf diese 4 Eigenschaften zu pruefen,
die *keine* gueltige Versionsnummer darstellen, und alles andere
muss dann ja wohl eine gueltige Versionsnummer sein.
case $VER in
.*) echo "Keine gültige Versionsnummer";;
*.) echo "Keine gültige Versionsnummer";;
*..*) echo "Keine gültige Versionsnummer";;
*[!0-9.]*) echo "keine gültige Versionsnummer";;
*) echo "Versionsnummer: $VER";;
esac
Erfuellt das nicht den von dir angestrebten Zweck? ...
Über den Negativ Ausschluss oder wie man es nenne will zu gehen ist
sicher auch eine Möglichkeit, bläst das ganze Script aber auch
wieder auf was ich immer zu vermeiden versuche. Auf der anderen
Seite sehe auch ich als nicht Script Profi in jeder Zeile ganz
genau auf was geprüft wird. Klassische Zwickmühle. ;-)
Und das ganz genaue Sehen ist ein unschätzbarer Vorteil:  So kannst
Du auch in 2 Jahren, wenn Du das Skript wiederverwenden willst, noch
verstehen, was Du heute programmiert hattest. 

Um dem Aufblasen etwas entgegenzusetzen, steck den Test im Skript in
eine Funktion:

versionsnummer_gueltig()
{
# Diese Funktion prueft, ob der ihr uebergebene Parameter aus
# einer Folge von Ziffern, in die einzelne Punkte gestreut sein
# duerfen, besteht. Am Anfang und am Ende darf kein Punkt
# stehen. Punkte duerfen nicht direkt nebeneinander stehen.
# Es muss wenigstens eine Ziffer enthalten sein.
#
# Anders ausgedrueckt: Die Funktion ist zufrieden, wenn die
# folgende Bedingung erfüllt ist: Der Parameter beginnt mit
# einer oder mehreren Ziffern. Dann duerfen null oder mehrere
# Abschnitte folgen, von denen jeder mit einem Punkt beginnt,
# dem eine oder mehrere Ziffern folgen.

case "${1-}" in
.*)
# Beginnt die Zeichenfolge mit einem Punkt, ist sie
# ungueltig:
#
return 1 ;;
*.)
# Endet die Zeichenfolge mit einem Punkt, ist sie
# ungueltig:
#
return 1 ;;
*..*)
# Enthaelt die Zeichenfolge zwei aufeinander folgende
# Punkte, ist sie ungueltig:
#
return 1 ;;
*[!0123456789.]*)
# Enthaelt die Zeichenfolge mindestens ein Zeichen, das
# weder eine Ziffer noch ein Punkt ist (das Ausrufezeichen
# unmittelbar nach der oeffnenden eckigen Klammer
# bedeutet, die Komplementmenge zu bilden), ist sie
# ungueltig:
#
return 1;;

# Ab hier koennen keine falschen Zeichen mehr in der
# Zeichenfolge vorkommen, nur noch Ziffern und Punkte, und
# die Punkte nur da, wo sie erlaubt sind. Es kann
# allerdings sein, dass gar keine Zeichen in der
# Zeichenfolge sind. Dann waere die Zeichenfolge leer.
# Das muss also noch ausgeschlossen werden:
'')
# Dieser Test passt nur auf die leere Zeichenfolge.
# Die ist auch ungueltig:
#
return 1;;

# Hier bleiben nur noch gueltige Zeichenfolgen uebrig.
# Das case-esac-Kommando endet mit exit status 0.
esac
}

Dann muss man die Meldung «keine gültige Versionsnummer» nur einmal
ins Skript schreiben, anstelle sie bei jedem Teil‐Test innerhalb der
Funktion zu wiederholen.  Außerdem trennt man so die Erkennung
korrekter (bzw. inkorrekter) Versionsnummern von der Fehlermeldung. 
(Stell Dir vor, Du möchtest den Versionsnummerntest später einmal
ohne Fehlermeldung verwenden, dann würde die Fehlermeldung innerhalb
der Funktion nur stören.)  Und so verwendest Du die Funktion dann:

aufforderung="$(
echo -e '\033[32mVersionsnummer angeben:\033[0m'
) " &&
until
read -p "$aufforderung" VER &&
versionsnummer_gueltig "$VER"
do
printf '%s\n' \
"$VER"' ist keine gültige Versionsnummer.' \
'Bitte mach einen neuen Versuch.'
done
# Ab hier enthaelt "$VER" zwangslaeufig eine gueltige
# Versionsnummer.

Vorteile:

Beim Versuch, zu verstehen, was das Skript macht, schaust Du Dir
zuerst die Funktion an und erkennst:  Sie liefert den exit status 0
(= «alles in Ordnung»), wenn die übergebene Zeichenfolge eine
gültige Versionsnummer darstellt, ansonsten den exit status 1 (=
«Versionsnummer nicht gültig»).  Das wird auch durch ihren Namen
und den Kommentar in ihr ausgedrückt.

Dann schaust Du Dir die «until»‐Schleife an:  Sie beginnt mit einem
Test.  Der Test fragt nach der Versionsnummer und prüft sie:  Wenn
der Test den exit status 0 liefert, wird die Schleife beendet. 
Ansonsten wird der Schleifenrumpf einmal durchlaufen.  Im
Schleifenrumpf erhältst Du die Fehlermeldung.  Dann wird wieder von
vorne mit dem Test (mitsamt der Eingabemöglichkeit) angefangen.

=> Wenn die Schleife zu Ende gekommen ist, war der Test erfolgreich
(exit status 0), denn vorher kommt sie nicht zu Ende.  => Die
Funktion «versionsnummer_gueltig» war mit der Versionsnummer
zufrieden.  => "$VER" enthält eine gültige Versionsnummer.  Das
drückt auch der Kommentar nach der Schleife aus.

Einen Hinweis noch:  Du hast die Shell‐Variable, die die
Versionsnummer enthalten soll, «VER» genannt (und ich habe das mal
so stehen gelassen).  Variablennamen, die nur aus Großbuchstaben
(und Unterstrichen und Ziffern) bestehen, werden per Konvention für
Umgebungsvariable freigehalten.  Daher würde ich einen anderen Namen
wählen.
Post by Detlef Paschke
Ich habe es jetzt noch nicht versucht aber wenn ich die Zeile in
meinem Script so einsetze,
*[0-9.]*) echo "Versionsnummer: $VER"; break;;
könnte es doch auch schon besser sein oder?
Dann hätte in meiner Zeile ein * zu Beginn gefehlt um auszusagen,
dass ausschließlich Zahlen erlaubt sind?
Nein.  Das ist kein Extglob‐Muster.  Extglob‐Muster (schau im
Bash‐Handbuch nach!) enthalten alle ein Paar runder Klammern.  Das
hier ist ein «normales» Globbing‐Muster.  Dabei steht der Stern für
null oder mehr beliebige Zeichen, «[0-9.]» für ein Zeichen, das
entweder in der Zeichensortierung des Locales zwischen den Ziffern 0
und 9 einschließlich liegt (also meistens die Ziffern 0 bis 9) oder
ein Punkt ist.

«*[0-9.]*» passt demnach auf alles, was mit null oder mehr
beliebigen Zeichen anfängt, dann eine Ziffer oder einen Punkt
enthält und mit null oder mehr beliebigen Zeichen endet.
Post by Detlef Paschke
Post by Michael Ottenbruch
| do
| read -p ..... VER
| [[ $VER == *(+([0-9])\.)+([0-9]) ]] && break
| echo Nö
| done
bzw. mit gesetztem
| shopt -s extglob
| case $VER in
| *(+([0-9])\.)+([0-9]) ) echo "Versionsnummer: $VER"; break;;
| * ) echo "Keine gültige Versionsnummer";;
| esac
Das sind die zwei Varianten, die ich zunächst ins Auge gefasst hatte.
Wenn ich es richtig verstehe, wird geprüft auf eine Zahl, einen Punkt
und eine weitere Zahl?
Es wird auf eine oder mehrere nicht‐leere Ziffernfolgen, denen außer
der letzten Ziffernfolge je ein Punkt folgt, geprüft.
Post by Detlef Paschke
Auch hier noch einmal die Frage, ein- oder mehrstellige Zahl ist
bei der Prüfung bedeutungslos?
Nein, darauf kommt es an.
Post by Detlef Paschke
Aus Neugierde, was sagt überhaupt das erste + also dieses
*(+([0-9... in der Zeile aus.
Das Pluszeichen vor einem in runden Klammern eingefassten Teil in
den Extglob‐Mustern bedeutet:  Eine Zeichenfolge passt auf das
Muster, wenn sie aus einem oder mehreren auf einander folgenden
Teilen besteht, von denen jeder auf das Muster passt, das in den
runden Klammern hinter dem Pluszeichen steht.

Das Sternchen vor einem in runden Klammern eingefassten Teil in den
Extglob‐Mustern bedeutet:  Eine Zeichenfolge passt auf das Muster,
wenn sie aus null oder mehreren auf einander folgenden Teilen
besteht, von denen jeder auf das Muster passt, das in den runden
Klammern hinter dem Sternchen steht.

Das Extglob‐Muster «*(+([0-9])\.)+([0-9])» sagt folgendes aus:  Alle
Zeichenfolgen (in Deinem Fall also Versionsnummern), die darauf
passen, sind folgendermaßen aufgebaut:

Die Versionsnummern beginnen demnach mit null oder mehreren Teilen,
von denen jeder durch den ersten hinter dem «*» stehenden in runde
Klammern eingefassten Teil wie folgt beschrieben wird:

Er passt auf eine Zeichenfolge, die mit einem oder mehreren auf
einander folgenden Teilen beginnt, von denen jeder eine Ziffer ist;
und am Schluss kommt noch ein Teil, der auf das Muster «\.» (s. u.)
passt.

«+([0-9])» passt demnach auf eine Folge von einer oder mehreren
Ziffern.

Dann folgt im Muster oben der Teil «\.».  Der passt nur auf ein
einziges Zeichen: auf einen Punkt: «.».  (Der «\» ist hier unnötig,
schadet aber nicht; ich würde ihn weglassen.)

Am Schluss des Musters kommt noch einmal so ein bereits oben
beschriebener Teil: «+([0-9])»: eine Folge von einer oder mehreren
Ziffern.

Zusammengesetzt bedeutet das ganze Muster jetzt folgendes:  Am
Anfang der Versionsnummer stehen null oder mehr Teile, bestehend aus
je einer nicht‐leeren Ziffernfolge, der ein Punkt folgt.  Am
Schluss folgt noch eine nicht‐leere Ziffernfolge (aber kein Punkt
mehr).

Die Extglob‐Muster sind eine Spezialität des Bashs und vermutlich
noch anderer moderner Shells.  Sie sind aber im POSIX‐Standard für
Shells nicht enthalten.  Und da Du planst, das Skript auch zukünftig
einzusetzen (und vielleicht weiterzuverbreiten), wäre es eine
Überlegung wert, sich auf den POSIX‐Standard zu beschränken, weil
der eine sehr hohe Verbreitung hat.

Die Beschränkung ist möglich, wenn man statt der Extglob‐Muster
Jürgen Ilses Fassung mit den Ausschlusskriterien nutzt.  Sie kommt
ohne Extglob‐Muster aus und beschränkt sich auf die einfachen
Globbing‐Muster, die im POSIX‐Standard für Shells enthalten sind. 
Vermutlich läuft sie auch schneller (obwohl sie größer aussieht),
weil der Rechenaufwand kleiner ist.
Detlef Paschke
2021-06-10 07:47:04 UTC
Permalink
Am 06.06.2021 um 04:06 schrieb Helmut Waitzmann:

Hallo Helmut,

zunächst vielen Dank für Deine ausführliche Erklärung, die ich in Ruhe
durcharbeiten werde.
Vorerst nur diese kurze "Zwischenerklärung".
Post by Helmut Waitzmann
Post by Detlef Paschke
Ich war der Meinung, dass ich es recht genau in meiner Fragestellung
beschrieben hatte. "Im betreffenden Script soll eine Versionsnummer
abgefragt werden, welche aus einer unbekannten Anzahl von Zahlen und
ebenso unbekannt vielen Punkten bestehen kann. (NN.NN.NN)". Die Angabe
"N" sollte eine Zahl interpretieren.
Da fangen die Schwierigkeiten schon an:  Wenn «N» für eine Zahl,
also vermutlich eine Ziffernfolge, steht, wofür steht dann «NN»? 
Für zwei aneinander geklebte Ziffernfolgen, demnach also eine
mindestens zweistellige Zahl?  Da hättest Du doch sicher «‹N› soll
eine zwei‐ oder mehrstellige Zahl sein» geschrieben, anstelle zwei
mindestens einstellige Zahlen aneinanderzukleben, nicht?  Also wird
der mitdenkende Leser schließen:  Ah, er verwechselt den Begriff
Zahl mit dem Begriff Ziffer.  Also meint er, dass «N» für eine
Ziffer steht.  Damit meint folgerichtig das Muster «NN.NN.NN» also
drei zweistellige Zahlen, mit je einem Punkt verbunden.  Und wo hat
jetzt die unbekannte Anzahl noch Platz?
Das hat jetzt mit der Frage «Wie kriege ich einen entsprechenden
Test ins Skript rein?» noch gar nichts zu tun.  Es scheitert bereits
daran, genau zu beschreiben, wie Versionsnummern aussehen sollen. 
Und das scheitert bereits daran, dass Du in der Beschreibung
zwischen Ziffern und Zahlen nicht sorgfältig unterscheidest.
Ich habe in der Tat Zahl anstelle Ziffer eingesetzt.
Für das derzeit genutzte Programm lautet die Versionsnummer z.B. 6.0.0
in der von mir in der Fragestellung eingesetzten Schreibweise also (N.N.N).
Da ich das Script wie geschrieben, evtl. auch für andere Programme
einsetzen möchte und auch das derzeitig eingesetzte natürlich höhere
Versionsnummern bekommen wird, schrieb ich von der "unbekannten Anzahl"
von Punkten und Ziffern, (falsch ausgedrückt, schrieb ich Zahlen) da bei
einem anderen Programm die Versionsnummer durchaus 1234.14 lauten
könnte. In der von mir unklug benutzten Schreibweise also (NNNN.NN).

Im Endeffekt will ich erreichen, dass bei der Prüfung ausschließlich die
Eingabe von Ziffern und Punkten akzeptiert wird.
Bindestriche und Angaben wie "svn" kann man evtl. später noch hinzufügen.

Nun habe ich gestern Abend irgend wo gelesen, dass das mit case gar
nicht gehen kann, weil case wohl nur auf ein Zeichen prüft.
Post by Helmut Waitzmann
Einen Hinweis noch:  Du hast die Shell‐Variable, die die
Versionsnummer enthalten soll, «VER» genannt (und ich habe das mal
so stehen gelassen).  Variablennamen, die nur aus Großbuchstaben
(und Unterstrichen und Ziffern) bestehen, werden per Konvention für
Umgebungsvariable freigehalten.  Daher würde ich einen anderen Namen
wählen.
Das werde ich gleich ändern.
Alles andere muss ich mir erst in Ruhe durcharbeiten.

Viele Grüße
Detlef Paschke
--
Das "Zitat des Augenblicks" gibt es nur auf
http://schabau.eu
Meine "Merkzettel"
http://helpdesk.schabau.eu
Michael Ottenbruch
2021-06-10 08:35:42 UTC
Permalink
Post by Detlef Paschke
Nun habe ich gestern Abend irgend wo gelesen, dass das mit case gar
nicht gehen kann, weil case wohl nur auf ein Zeichen prüft.
Das ist Unsinn. Wie man an den beiden Beispielen sehen kann, ist case
durchaus in der Lage, auf Zeichenfolgen zu prüfen.

| case word in [ [(] pattern [ | pattern ] ... ) list ;; ] ... esac
| A case command first expands word, and tries to match it against each pattern in turn, using the match-
| ing rules described under Pattern Matching below. The word is expanded using tilde expansion, parame-
| ter and variable expansion, arithmetic expansion, command substitution, process substitution and quote
| removal. Each pattern examined is expanded using tilde expansion, parameter and variable expansion,
| arithmetic expansion, command substitution, and process substitution.

Wenn pattern tatsächlich nur aus einem Zeichen bestehen dürfte, wäre es
schwierig, "tilde expansion, parameter and variable expansion,
arithmetic expansion, command substitution, and process substitution"
daran durchzuführen.
--
...und tschuess!

Michael
E-mail: ***@sailor.ping.de
Detlef Paschke
2021-06-11 16:09:06 UTC
Permalink
Am 10.06.2021 um 10:35 schrieb Michael Ottenbruch:

Hallo Michael,
Post by Michael Ottenbruch
Post by Detlef Paschke
Nun habe ich gestern Abend irgend wo gelesen, dass das mit case gar
nicht gehen kann, weil case wohl nur auf ein Zeichen prüft.
Das ist Unsinn. Wie man an den beiden Beispielen sehen kann, ist case
durchaus in der Lage, auf Zeichenfolgen zu prüfen.
okay, dann lösche ich diese Falschinformation wieder, vielen Dank.
Das ist mir auch viel lieber, an case habe ich mich gerade ran getastet
und gewöhnt.

Bei if when ging für mich verständlich nur "mach richtig, eine zweite
Chance gibt es nicht".

Bei case kann ich für mich verständlich schreiben "nee, das ist Falsch,
versuch noch mal".

Viele Grüße
Detlef Paschke
--
Das "Zitat des Augenblicks" gibt es nur auf
http://schabau.eu
Meine "Merkzettel"
http://helpdesk.schabau.eu
Juergen Ilse
2021-06-15 02:44:57 UTC
Permalink
Hallo,
Post by Detlef Paschke
Nun habe ich gestern Abend irgend wo gelesen, dass das mit case gar
nicht gehen kann, weil case wohl nur auf ein Zeichen prüft.
Nein. Bei casewird dder gesamte Inhalt der benutzten Variable gegen
"shell-wildcards" gematched, ud mit shell-wildcards kann man das, auf
das du gern pruefen moechtest, nicht mit einem Ausdruck abbilden.
Mit "regular expressions" ginge das, aber eben nicht mit shellwildcards.
Man kann aber alle Ausdruecke, die *nicht* dem von dir gewuenschten
Muster entsprechen, durch matchen gegen verschiedene wildcards erreichen.
Deswegen mein Vorschlag mit den mehreren "case" Zweigen.

Tschuess,
Juergen Ilse (juergenqusenet-verwaltung.de)
David Haller
2021-06-15 04:01:20 UTC
Permalink
Post by Juergen Ilse
Post by Detlef Paschke
Nun habe ich gestern Abend irgend wo gelesen, dass das mit case gar
nicht gehen kann, weil case wohl nur auf ein Zeichen prüft.
Nein. Bei casewird dder gesamte Inhalt der benutzten Variable gegen
"shell-wildcards" gematched, ud mit shell-wildcards kann man das, auf
das du gern pruefen moechtest, nicht mit einem Ausdruck abbilden.
Mit "regular expressions" ginge das, aber eben nicht mit shellwildcards.
Man kann aber alle Ausdruecke, die *nicht* dem von dir gewuenschten
Muster entsprechen, durch matchen gegen verschiedene wildcards erreichen.
Deswegen mein Vorschlag mit den mehreren "case" Zweigen.
Kann man auch in anderen Shells als der Bash nicht auch die
case-Zweige zusammenfassen? Also sowas:

case "${1-}" in
.* | *. | *..* | *[!0123456789.]* | '' )
printf "Keine gültige Versionsnummer\n" >&2;
return 1
;;
*) mach_was_mit_der_nummer;;
esac

Oder ist das ein Bashismus?

-dnh
--
One observes the survivors, and learns from them.
-- Bene Gesserit Teaching
Christian Weisgerber
2021-06-15 13:39:38 UTC
Permalink
Post by David Haller
Kann man auch in anderen Shells als der Bash nicht auch die
case "${1-}" in
.* | *. | *..* | *[!0123456789.]* | '' )
printf "Keine gültige Versionsnummer\n" >&2;
return 1
;;
Kann man.
--
Christian "naddy" Weisgerber ***@mips.inka.de
j***@schily.net
2021-06-15 22:56:57 UTC
Permalink
Post by David Haller
Kann man auch in anderen Shells als der Bash nicht auch die
case "${1-}" in
.* | *. | *..* | *[!0123456789.]* | '' )
printf "Keine gültige Versionsnummer\n" >&2;
return 1
;;
*) mach_was_mit_der_nummer;;
esac
Oder ist das ein Bashismus?
Wenn Du das Pipe Zeichen bei case meinst, das wurde 1976 vom Bourne Shell
eingeführt, das können alle Kompatiblen.
--
EMail:***@schily.net Jörg Schilling D-13353 Berlin
Blog: http://schily.blogspot.com/
URL: http://cdrecord.org/private/ http://sourceforge.net/projects/schilytools/files/
Detlef Paschke
2021-06-19 08:48:21 UTC
Permalink
Post by David Haller
Kann man auch in anderen Shells als der Bash nicht auch die
case "${1-}" in
.* | *. | *..* | *[!0123456789.]* | '' )
printf "Keine gültige Versionsnummer\n" >&2;
return 1
;;
*) mach_was_mit_der_nummer;;
esac
Ich habe den Vorschlag von Helmut in fast der selben Weise für mich
abgeändert und benutzt.

{
case "${1-}" in
.* | *. | *..* | *[!0-9.]* | '' )
# Beginnt die Zeichenfolge mit einem Punkt, endet sie mit einem
# Punkt, enthält sie zwei aufeinander folgende Punkte, enthält
# sie andere Zeichen als Ziffern und Punkte oder ist sie leer,
# so ist sie ungültig.
return 1 ;;
esac
}

Und ich habe printf gegen echo ausgetauscht, weil ich mit printf einfach
noch nicht so richtig klarkomme. Wenn ich es besser verstehe, setze ich
auch printf anstelle echo ein.

Helmut,
eine Frage am Rand zu der ich auch bei längerem Suchen (wahrscheinlich
wieder nicht der richtige Suchbegriff), keine Antwort gefunden habe.

Du benutzt hier um die Eingabe zu definieren (kann man es so
ausdrücken?) diesen Syntax:
case "${1-}"

Vor einiger Zeit hast Du mir bei einem anderen Skript geholfen und dort
diesen Syntax verwendet:
while ${1+:}

Das übliche was ich kenne um zu sagen "es betrifft die Eingabe" ist
dieser Syntax:
case "$1"

Ich konnte nichts zum Unterschied zwischen den Schreibweisen
$1, 1+ oder 1- finden.

Viele Grüße
Detlef Paschke
--
Das "Zitat des Augenblicks" gibt es nur auf
http://schabau.eu
Meine "Merkzettel"
http://helpdesk.schabau.eu
Michael Ottenbruch
2021-06-19 11:09:01 UTC
Permalink
Post by Detlef Paschke
Du benutzt hier um die Eingabe zu definieren (kann man es so
case "${1-}"
Vor einiger Zeit hast Du mir bei einem anderen Skript geholfen und dort
while ${1+:}
Das übliche was ich kenne um zu sagen "es betrifft die Eingabe" ist
case "$1"
Ich konnte nichts zum Unterschied zwischen den Schreibweisen
$1, 1+ oder 1- finden.
Auch das findest Du mit "man bash", und zwar unter "Parameter
Expansion":

| Parameter Expansion
| The `$' character introduces parameter expansion, command substitution, or arithmetic expansion. The parame-
| ter name or symbol to be expanded may be enclosed in braces, which are optional but serve to protect the vari-
| able to be expanded from characters immediately following it which could be interpreted as part of the name.
|
| When braces are used, the matching ending brace is the first `}' not escaped by a backslash or within a quoted
| string, and not within an embedded arithmetic expansion, command substitution, or parameter expansion.
|
| ${parameter}
| The value of parameter is substituted. The braces are required when parameter is a positional parame-
| ter with more than one digit, or when parameter is followed by a character which is not to be inter-
| preted as part of its name. The parameter is a shell parameter as described above PARAMETERS) or an
| array reference (Arrays).
|
| [...]
|
| When not performing substring expansion, using the forms documented below (e.g., :-), bash tests for a parame-
| ter that is unset or null. Omitting the colon results in a test only for a parameter that is unset.
|
| ${parameter:-word}
| Use Default Values. If parameter is unset or null, the expansion of word is substituted. Otherwise,
| the value of parameter is substituted.
|
| [...]
|
| ${parameter:+word}
| Use Alternate Value. If parameter is null or unset, nothing is substituted, otherwise the expansion of
| word is substituted.

D.h.: "${1-}" setzt einen ungesetzten Parameter auf einen leeren String,
"${1+:}" ersetzt einen gesetzten Parameter durch ":", wobei mir etwas
schleierhaft ist, in welcher konkreten Situation das nützlich wäre, denn
":" ist ein bash-Befehl, der nichts tut:

| : [arguments]
| No effect; the command does nothing beyond expanding arguments and performing any specified redirec-
| tions. The return status is zero.

Falls es sich um einen Tippfehler handeln sollte: "${1:+}" ersetzt einen
gesetzten Parameter durch einen leeren String, sofern er nicht schon ein
leerer String ist.
--
...und tschuess!

Michael
E-mail: ***@sailor.ping.de
Detlef Paschke
2021-06-19 19:55:44 UTC
Permalink
Post by Michael Ottenbruch
D.h.: "${1-}" setzt einen ungesetzten Parameter auf einen leeren String,
"${1+:}" ersetzt einen gesetzten Parameter durch ":", wobei mir etwas
schleierhaft ist, in welcher konkreten Situation das nützlich wäre, denn
Ein Stück weiter unten, "Bash Script mit mehreren Parametern" steht der
Beitrag noch und das Script macht klaglos seinen Dienst.

Viele Grüße
Detlef Paschke
--
Das "Zitat des Augenblicks" gibt es nur auf
http://schabau.eu
Meine "Merkzettel"
http://helpdesk.schabau.eu
Michael Ottenbruch
2021-06-19 22:59:35 UTC
Permalink
Post by Detlef Paschke
Post by Michael Ottenbruch
D.h.: "${1-}" setzt einen ungesetzten Parameter auf einen leeren String,
"${1+:}" ersetzt einen gesetzten Parameter durch ":", wobei mir etwas
schleierhaft ist, in welcher konkreten Situation das nützlich wäre, denn
Ein Stück weiter unten, "Bash Script mit mehreren Parametern" steht der
Beitrag noch und das Script macht klaglos seinen Dienst.
Und ab <s0ekei$og93$***@yggdrasil.dn.cgarbs.de> folgt die Diskussion, was
die Abfrage bewirkt. Ich hatte mich an der Diskussion sogar beteiligt,
weil ich es zunächst nicht verstanden hatte. Leider hatte ich das nach
vier Monaten schon nicht mehr auf dem Schirm ... ;-\

Unklar ist mir nun allerdings, wie Du schreiben kannst:

| eine Frage am Rand zu der ich auch bei längerem Suchen (wahrscheinlich
| wieder nicht der richtige Suchbegriff), keine Antwort gefunden habe.
|
| [...]
|
| Ich konnte nichts zum Unterschied zwischen den Schreibweisen
| $1, 1+ oder 1- finden.

Denn bereits in der oben genannten Diskussion finden sich Hinweise auf
den und Zitate aus dem Abschnitt zu "Parameter Expansion" aus der
bash-Manpage.
--
...und tschuess!

Michael
E-mail: ***@sailor.ping.de
Detlef Paschke
2021-06-23 20:03:17 UTC
Permalink
Post by Michael Ottenbruch
Post by Detlef Paschke
Ein Stück weiter unten, "Bash Script mit mehreren Parametern" steht der
Beitrag noch und das Script macht klaglos seinen Dienst.
die Abfrage bewirkt. Ich hatte mich an der Diskussion sogar beteiligt,
weil ich es zunächst nicht verstanden hatte. Leider hatte ich das nach
vier Monaten schon nicht mehr auf dem Schirm ... ;-\
| eine Frage am Rand zu der ich auch bei längerem Suchen (wahrscheinlich
| wieder nicht der richtige Suchbegriff), keine Antwort gefunden habe.
|
| [...]
|
| Ich konnte nichts zum Unterschied zwischen den Schreibweisen
| $1, 1+ oder 1- finden.
Denn bereits in der oben genannten Diskussion finden sich Hinweise auf
den und Zitate aus dem Abschnitt zu "Parameter Expansion" aus der
bash-Manpage.
Das ist ganz einfach erklärt. Ich habe meine Suche in Google
durchgeführt und zum angesprochenen Beitrag ist es ganz schnell Erklärt.
Meine Frage wurde mir sehr detailliert und für mich als Script-Laien
verständlich von Helmut Waitzmann beantwortet und entsprechende
Vorschläge gemacht. Diese habe ich für mich angepasst umgesetzt und so
arbeitet das betreffende Script seither problemlos.
Den weiteren Verlauf der Diskursiv unter den Profis habe ich versucht
noch ein Weilchen zu folgen, bin dann jedoch ausgestiegen weil ich
nichts mehr vom geschriebenen verstanden habe und habe somit wohl auch
nicht die Erklärung von ${1+:} mitbekommen.

Mag der mich dafür verurteilen, der alles von allem versteht.

Viele Grüße
Detlef Paschke
--
Das "Zitat des Augenblicks" gibt es nur auf
http://schabau.eu
Meine "Merkzettel"
http://helpdesk.schabau.eu
Helmut Waitzmann
2021-06-19 23:44:28 UTC
Permalink
Post by Michael Ottenbruch
Post by Detlef Paschke
Du benutzt hier um die Eingabe zu definieren (kann man es so
case "${1-}"
Vor einiger Zeit hast Du mir bei einem anderen Skript geholfen
while ${1+:}
Das übliche was ich kenne um zu sagen "es betrifft die Eingabe"
case "$1"
Ich konnte nichts zum Unterschied zwischen den Schreibweisen
$1, 1+ oder 1- finden.
Auch das findest Du mit "man bash", und zwar unter "Parameter
[…]
Post by Michael Ottenbruch
D.h.: "${1-}" setzt einen ungesetzten Parameter auf einen leeren String,
Das stimmt nicht ganz:  «${1-Ersatz}» liefert, falls der Parameter 1
vorhanden ist, dasselbe wie «$1».  Ist der Parameter 1 jedoch nicht
vorhanden, kommt statt dessen «Ersatz» heraus.  Für «Ersatz» kann
man natürlich auch die leere Zeichenkette «''» oder sogar gar nichts
hinschreiben.  Der Parameter 1 bleibt in jedem Fall, wie er ist,
wird also nicht neu gesetzt.
Post by Michael Ottenbruch
"${1+:}" ersetzt einen gesetzten Parameter durch ":", wobei mir
etwas schleierhaft ist, in welcher konkreten Situation das nützlich
| : [arguments]
| No effect; the command does nothing beyond
| expanding arguments and performing any specified
| redirections. The return status is zero.
Der letzte Satz ist hier der interessanteste:  Das Shell‐Kommando


${1+:} false


läuft im Fall, dass der Parameter 1 vorhanden ist, auf das Kommando


: false

hinaus.  Das tut nichts weiter, sondern beendet sich nur mit return
status 0.

Im Fall, dass der Parameter 1 nicht vorhanden ist, läuft das oben
angeführte Shell‐Kommando auf das Kommando

false

hinaus.  Das tut ebenfalls nichts weiter, aber beendet sich mit
return status 1.

=> Ist der Parameter 1 vorhanden, gibt es status 0; ist er nicht
vorhanden, gibt es status 1.  => Damit lässt sich in einem
Shell‐Skript abfragen, ob der Parameter 1 vorhanden ist:

if ${1+:} false
then
printf '%s\n' 'Den Parameter 1 gibt es.'
else
printf '%s\n' 'Den Parameter 1 gibt es nicht.'
fi

Oder man kann die Reihe der Parameter in einer Schleife einzeln
verarbeiten:

nummer=0
while ${1+:} false
do
printf 'Parameter Nr. %s ist %s\n' \
"$((nummer += 1))" "$1"
shift 1
done

Bemerkungen:

Das Kommando «shift» entfernt von den Parametern, beim ersten
angefangen, so viele, wie angegeben, und lässt die folgenden
aufrücken.

Der Ausdruck «"$((nummer += 1))"» nimmt den Inhalt der Variablen
«nummer» als Zahl, zählt 1 dazu, speichert den neuen Wert in der
Variablen «nummer» und liefert ihn auch als Zeichenkette.
Post by Michael Ottenbruch
Falls es sich um einen Tippfehler handeln sollte: "${1:+}" ersetzt
einen gesetzten Parameter durch einen leeren String, sofern er
nicht schon ein leerer String ist.
Und im Fall, dass es den Parameter 1 nicht gibt, liefert «"${1:+}"»
ebenfalls eine leere Zeichenkette.  (Damit ist der Fall, wo zwischen
dem Pluszeichen und der schließenden Schweifklammer nichts steht,
nicht besonders effektvoll.)
Christian Garbs
2021-06-08 17:43:43 UTC
Permalink
Mahlzeit!
Post by Detlef Paschke
Post by Juergen Ilse
Wie waere es da, zuerst auf diese 4 Eigenschaften zu pruefen, die
*keine* gueltige Versionsnummer darstellen, und alles andere muss
dann ja wohl eine gueltige Versionsnummer sein.
case $VER in
.*) echo "Keine gültige Versionsnummer";;
*.) echo "Keine gültige Versionsnummer";;
*..*) echo "Keine gültige Versionsnummer";;
*[!0-9.]*) echo "keine gültige Versionsnummer";;
*) echo "Versionsnummer: $VER";;
esac
Erfuellt das nicht den von dir angestrebten Zweck? ...
Über den Negativ Ausschluss oder wie man es nenne will zu gehen ist
sicher auch eine Möglichkeit, bläst das ganze Script aber auch wieder
auf was ich immer zu vermeiden versuche. Auf der anderen Seite sehe auch
ich als nicht Script Profi in jeder Zeile ganz genau auf was geprüft
wird. Klassische Zwickmühle. ;-)
Gerade wenn Du nicht so Shellskripte schreibst, ist "das ist so
eindeutig, das kann ich auch in vier Wochen noch lesen" doch eine
wunderbare Eigenschaft. Gönn das Deinem zukünftigen Ich :-)

Solange das Skript nicht Teil einer hochwichtigen Anwendung ist, die
extrem performant sein muss, oder Du zum Spaß die kürzestmögliche
(unlesbare) Lösung suchst, sind ein paar Zeilen mehr im Skript nicht
schlimm. Weder eventuelle zusätzliche CPU-Millisekunden beim Parsen
noch 40 weitere Bytes auf der Festplatte kosten etwas. "Teuer" wird
es, wenn Du später nochmal eine Stunde rätseln musst, wie das Skript
funktioniert hat. Entwickler kosten mehr als Hardware ;-)

Gruß
Chris "das hatte jetzt wenig Shellbezug, aber trotzdem" tian
--
....Christian.Garbs....................................https://www.cgarbs.de
OH VEN
Helmut Waitzmann
2021-06-08 21:42:54 UTC
Permalink
Post by Christian Garbs
Post by Detlef Paschke
Post by Juergen Ilse
Wie waere es da, zuerst auf diese 4 Eigenschaften zu pruefen, die
*keine* gueltige Versionsnummer darstellen, und alles andere muss
dann ja wohl eine gueltige Versionsnummer sein.
case $VER in
.*) echo "Keine gültige Versionsnummer";;
*.) echo "Keine gültige Versionsnummer";;
*..*) echo "Keine gültige Versionsnummer";;
*[!0-9.]*) echo "keine gültige Versionsnummer";;
*) echo "Versionsnummer: $VER";;
esac
Erfuellt das nicht den von dir angestrebten Zweck? ...
Über den Negativ Ausschluss oder wie man es nenne will zu gehen ist
sicher auch eine Möglichkeit, bläst das ganze Script aber auch wieder
auf was ich immer zu vermeiden versuche. Auf der anderen Seite sehe auch
ich als nicht Script Profi in jeder Zeile ganz genau auf was geprüft
wird. Klassische Zwickmühle. ;-)
Gerade wenn Du nicht so Shellskripte schreibst, ist "das ist so
eindeutig, das kann ich auch in vier Wochen noch lesen" doch eine
wunderbare Eigenschaft. Gönn das Deinem zukünftigen Ich :-)
Chris "das hatte jetzt wenig Shellbezug, aber trotzdem" tian
Ich glaube, es hat mehr Shell‐Bezug, als man denkt:  Ich vermute,
dass Jürgens Lösung mit den Ausschluss‐Mustern schneller läuft als
eine Lösung mit den Extglob‐Mustern:  Wenn das Muster der
Form

«null oder mehrere Male (eine oder mehrere Ziffern gefolgt von einem Punkt)
gefolgt von einer oder mehreren Ziffern»

vom Shell von vorne nach hinten abgearbeitet wird, kann es
vorkommen, dass der Shell beim Versuch, zu prüfen, ob die
Zeichenfolge passt, zurücksetzen muss.  Dann ist das Muster der Form

«eine oder mehrere Ziffern gefolgt von null oder mehreren Malen (ein
Punkt gefolgt von einer oder mehreren Ziffern)»

möglicherweise schneller, obwohl es auf dieselben Zeichenketten
passt.

Dazu heißt es bei mir im Bash‐Handbuch:  «Complicated extended
pattern matching against long strings is slow, especially when the
patterns contain alternations and the strings contain multiple
matches.  Using separate matches against shorter strings, or using
arrays of strings instead of a single long string, may be faster.»

Jürgens Ausschlusslösung hat das Problem nicht.
Lesen Sie weiter auf narkive:
Loading...