PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Bash - Abfrage ob es eine Zahl ist



woercel
18-02-2008, 07:52
Hallo,
ich habe folgendes Problem und zwar lese ich aus einer Datei verschiedene
Werte aus und rechne diese dann zusammen, jetzt kann es aber durchaus mal
vorkommen das beim anlegen dieser Datei ein Fehler passiert ist und die Zahl
nicht da ist oder wenns ne mehrstellige Zahl ist die Stellen mit nem "," trennt
statt mit nem Punkt.

Ist es irgendwie möglich mit ner einfachen if Abfrage festzustellen ob dies
jetzt eine Zahl ist die ich auch verwerten kann?

Ich habs mit if [ $Z1 -gt 0 ] versucht, naja :D aber des bringt nich wirklich
den gewünschten Erfolg.

Und wenn z.B. der Fehler mit dem "," auftritt, das man das dann mit nem "." ersetzt?

Cheers
woercel

Aqualung
18-02-2008, 16:40
mytest=$( echo $Z1 | grep "[0-9,]" | sed "s/\,/./")
if [ "$mytest" ]; then
echo "$mytest ist eine Zahl mit ."
fi


HTH Aqualung

ContainerDriver
18-02-2008, 19:37
mytest=$( echo $Z1 | grep "[0-9,]" | sed "s/\,/./")
if [ "$mytest" ]; then
echo "$mytest ist eine Zahl mit ."
fi


HTH Aqualung

Der reguläre Ausdruck da oben filtert aber nicht so gut...


mytest=$(echo $Z1|sed "s/,/./|egrep "^[0-9]*[\.]?[0-9]*$")
if [ "$mytest" ]; then
echo "$mytest ist eine Zahl mit ."
fi

jan61
21-02-2008, 01:24
Moin,


Der reguläre Ausdruck da oben filtert aber nicht so gut...


mytest=$(echo $Z1|sed "s/,/./|egrep "^[0-9]*[\.]?[0-9]*$")
if [ "$mytest" ]; then
echo "$mytest ist eine Zahl mit ."
fi


Der aber auch nicht - das ist syntaktisch falsch, es fehlt mindestens noch ein " nach dem sed. Und dann gibt das:
jan@jack:~/Data/mrunix> Z1=.
jan@jack:~/Data/mrunix> mytest=$(echo $Z1|sed "s/,/./" |egrep "^[0-9]*[\.]?[0-9]*$")
jan@jack:~/Data/mrunix> echo $mytest
.
jan@jack:~/Data/mrunix> if [ "$mytest" ]; then
> echo "$mytest ist eine Zahl mit ."
> fi
. ist eine Zahl mit .
Hm - da kann man sich drüber streiten, ob das eine Zahl sein soll ;-)

Die Frage ist, welche Syntax man als gültige Zahl annehmen will. Wenn man solche Muster (Ersetzen , durch . mal vorausgesetzt) akzeptieren will wie: 42 4.2 .42 42. 0.42 42.0, dann muss man Folgendes abprüfen:
- Ziffer(n), optional durch . und Ziffer(n) gefolgt
- optionale Ziffer(n), durch . und optionale Ziffer(n) gefolgt

Das ginge z. B. so (Negativprüfung - wenn nach dem sed was übrig bleibt, dann ist es ein Fehler):
jan@jack:~/Data/mrunix> echo "42
4.2
.4 2
42+.
0.42
42.a0" | while read z; do
> test -z "`echo $z | sed -r 's/^[0-9]+\.?[0-9]*$//;s/^[0-9]*\.?[0-9]+$//'`" && echo "$z ist eine Zahl"
> done
42 ist eine Zahl
4.2 ist eine Zahl
0.42 ist eine Zahl
Jan

ContainerDriver
21-02-2008, 11:32
Hallo.


Moin,
Der aber auch nicht - das ist syntaktisch falsch, es fehlt mindestens noch ein " nach dem sed.


Okay, in Zukunft werde wirklich nur noch die Befehle direkt nach dem Testen aus dem Terminalfenster rauskopieren. ;)



Und dann gibt das:
jan@jack:~/Data/mrunix> Z1=.
jan@jack:~/Data/mrunix> mytest=$(echo $Z1|sed "s/,/./" |egrep "^[0-9]*[\.]?[0-9]*$")
jan@jack:~/Data/mrunix> echo $mytest
.
jan@jack:~/Data/mrunix> if [ "$mytest" ]; then
> echo "$mytest ist eine Zahl mit ."
> fi
. ist eine Zahl mit .
Hm - da kann man sich drüber streiten, ob das eine Zahl sein soll ;-)

Ja, den Fall hatte ich mir auch überlegt... ist aber wohl besser den "." nicht als Zahl zuzulassen. bc z.B. meckert nicht


florian@leuchtturm0:~/tmp$ echo "5 + . + 1.2"|bc
6.2
mit sleep gibt es aber eine Fehlermeldung.


Wenn wir gerade dabei sind, können wir auch noch negative Zahlen zur Überprüfung hinzufügen (hoffe es ist jetzt kein Fehler drinnen). :)


sed -r 's/^-?[0-9]+\.?[0-9]*$//;s/^-?[0-9]*\.?[0-9]+$//'


EDIT: was mir noch eben eingefallen ist: " 9" würde jetzt gar nicht von dem regulären Ausdruck als Zahl erkannt werden, eventuell sollte man das ^ und $ weglassen.

jan61
21-02-2008, 19:22
Moin,


...EDIT: was mir noch eben eingefallen ist: " 9" würde jetzt gar nicht von dem regulären Ausdruck als Zahl erkannt werden, eventuell sollte man das ^ und $ weglassen.

Wieso soll 9 nicht als Zahl erkannt werden???
jan@jack:~/tmp/tartest> echo "-9" |while read z; do test -z "`echo $z | sed -r 's/^-?[0-9]+\.?[0-9]*$//;s/^[0-9]*\.?[0-9]+$//'`" && echo "$z ist eine Zahl"; done
-9 ist eine Zahl
jan@jack:~/tmp/tartest> echo "9" |while read z; do test -z "`echo $z | sed -r 's/^-?[0-9]+\.?[0-9]*$//;s/^-?[0-9]*\.?[0-9]+$//'`" && echo "$z ist eine Zahl"; done
9 ist eine Zahl
Jan

ContainerDriver
21-02-2008, 21:10
Ich meinte (z.B.) " 9" (mit einem Leerzeichen vor der 9!). In deinem Code


echo " 9 " |while read z; do test -z "`echo $z | sed -r 's/^-?[0-9]+\.?[0-9]*$//;s/^-?[0-9]*\.?[0-9]+$//'`" && echo "$z ist eine Zahl"; done
9 ist eine Zahl

macht das keinen Unterschied, ob vor oder nach der Zahl Leerzeichen stehen, weil read die entfernt. Will man jetzt aber


echo " 9 "|sed -r 's/^-?[0-9]+\.?[0-9]*$//;s/^[0-9]*\.?[0-9]+$//'
ausführen, wird nichts ersetzt (wegen den Zeilenanfang- und Zeilenendezeichen).

Gruß, FLorian

jan61
22-02-2008, 00:49
Moin,


Ich meinte (z.B.) " 9" (mit einem Leerzeichen vor der 9!).

ah, jetzt ist es klar. Die Leerzeichen kann man aber genauso wie das Komma "vorwaschen" - also vor der eigentlichen Prüfung entfernen. Dann sollte man aber aufpassen, dass man nur die am Anfang und Ende entfernt, sonst wird das Ergebnis verfälscht. Und wenn man ^ und $ aus dem sed weglässt, dann geben Leerzeichen einen Fehler - sie werden ja durch den sed nicht weggeputzt:
jan@jack:~/tmp> test -n "`echo \" 9 \"|sed -r 's/-?[0-9]+\.?[0-9]*//;s/[0-9]*\.?[0-9]+//'`" && echo "keine Zahl"
keine Zahl
Man muss sich also vorher schon genau überlegen, welche Toleranz man den Eingaben gegenüber walten lässt und wie penibel man prüft.

Jan