In bash auf Integer prüfen

Post Reply
Message
Author
hammerp
Posts: 18
Joined: 11. Jun 2002 0:12

In bash auf Integer prüfen

#1 Post by hammerp »

Hi Jungs,
wie kann ich in der bash prüfen ob eine Variable eine Integer ist?
Vielen Dank im Voraus.
hammerP

rattengift

Re: In bash auf Integer prüfen

#2 Post by rattengift »

<blockquote><pre><font size="1" face="">code:</font><hr><font face="Courier New" size="2">VARIABLE=.....
if $(echo $VARIABLE | grep -q '^[0-9]\+$'); then
echo integer
else
echo string
fi</font><hr></pre></blockquote>das suchmuster für grep beschreibt eine zeichenfolge, die ausschliesslich ziffern (aber davon mindestens eine) enthält.
"-q" unterdrückt die ausgabe von grep. stattdessen wird nur der exit status zurückgegeben.

Jochen

Re: In bash auf Integer prüfen

#3 Post by Jochen »

1. Die '\<!--no-->+'-Notation ist eine GNU-grep-Spezialität, ebenso wie die Option '-q'; portabel wäre entweder <pre>grep '^[<!--no-->0-9][<!--no-->0-9]*$' &>-</pre> oder <pre>egrep '^[<!--no-->0-9]+$' &>-</pre>('&>-' ist die bash-Version von '>/dev/null 2>/dev/null', aber die bash war ja explizit erwünscht.)


2. Je nachdem, wieviele Integers zu testen sind, sollte man auf den Aufruf eines externen Kommandos wie grep verzichten, da die bash so etwas natürlich auch eingebaut hat. In der einfachsten Form wäre das <pre>if [[ -n "$VAR" && -z "${VAR##[0-9]*}" ]] ; then ...</pre>Will man auch auf ein optionales Vorzeichen testen, muss man erst die erweiterten Globbing-Mechanismen mittels "shopt -s extglob" aktivieren. Die Lösung wäre dann<blockquote><pre><font size="1" face="">code:</font><hr><font face="Courier New" size="2">shopt -s extglob

if [[ -n "$VAR" && -z "${VAR##?([<!--no-->-+])+([<!--no-->0-9])}" ]] ; then
echo "\<!--no-->$VAR ist Integer: $VAR"
else
echo "\<!--no-->$VAR ist *nicht* Integer: $VAR"
fi
</font><hr></pre></blockquote>Siehe auch "man bash", Sektion "Parameter Expansion" für die ${VAR##}-Syntax, Sektion "Pattern Matching" für die ?([<!--no-->-+]) und +([<!--no-->0-9]) Syntax und Sektion "CONDITIONAL EXPRESSIONS" für die Optionen -n und -z bei [<!--no-->[<!--no--> <!--no-->]].

Jochen

rattengift

Re: In bash auf Integer prüfen

#4 Post by rattengift »

Hi Jochen,

parameter expansion war auch mein erster gedanke; ich hab irrtümlicherweise angenommen, dass dort keine regexps gehen.

> portabel wäre entweder grep '^[0-9][0-9]*$' &>- oder egrep '^[0-9]+$' &>-

soll das heissen, dass egrep "portabler" ist als gnu-grep? wenn ja, dann werde ich es in zukunft öfter verwenden. ich habe es bisher immer vermieden (obwohl es schneller und mächtiger ist als grep), gerade weil ich dachte, es sei *weniger* portabel.

hammerp
Posts: 18
Joined: 11. Jun 2002 0:12

Re: In bash auf Integer prüfen

#5 Post by hammerp »

@Jochen:
Mir gefällt die Idee ohne grep sehr gut. Allerdings kann ich es nicht ganz nachvollziehen und es gibt auch dann true zurück, wenn der Inhalt der Variable aus Zahlen und Buchstaben besteht und das erste Zeichen eine Zahl ist, zB: 2asdf
Wie kann man das noch verbessern?

Jochen

Re: In bash auf Integer prüfen

#6 Post by Jochen »

> Mir gefällt die Idee ohne grep sehr gut.

So weit, so gut...

> Allerdings kann ich es nicht ganz nachvollziehen und es gibt auch dann true zurück, wenn der Inhalt der Variable aus Zahlen und Buchstaben besteht und das erste Zeichen eine Zahl ist, zB: 2asdf

... und da fangen die Probleme an. Vor allem, weil <i>ich</i> sie nicht nachvollziehen kann <img src="http://www.pl-forum.de/UltraBoard/Images/Happy.gif" border="0" align="middle">. Ich habe das Skript mittels Cut'n'Paste aus meinem Posting kopiert (um Tippfehler zu vermeiden) und um ein paar Testwerte erweitet: <blockquote><pre><font size="1" face="">code:</font><hr><font face="Courier New" size="2">#!/bin/bash

shopt -s extglob

for VAR in 123 +123 -123 abc123 123abc +123abc -123abc +abc123 -abc123 ; do
if [[ -n "$VAR" && -z "${VAR##?([-+])+([0-9])}" ]] ; then
echo "\$VAR ist Integer: $VAR"
else
echo "\$VAR ist *nicht* Integer: $VAR"
fi
done

</font><hr></pre></blockquote>Und das Ergebnis ist eigentlich wie erwartet:<blockquote><hr>$VAR ist Integer: 123
$VAR ist Integer: +123
$VAR ist Integer: -123
$VAR ist *nicht* Integer: abc123
$VAR ist *nicht* Integer: 123abc
$VAR ist *nicht* Integer: +123abc
$VAR ist *nicht* Integer: -123abc
$VAR ist *nicht* Integer: +abc123
$VAR ist *nicht* Integer: -abc123
<hr></blockquote>Man beachte vor allen die Ausgabezeilen 4,5 und 6. Daher würde ich erst mal auf einen Tappfehler Deinerseits tappen - äh, tippen und vorschlagen, auch für einen ersten Test das Beispielskript mittels Cut'n'Paste zu übernehmen. (bash-Version bei mir ist übrigens 2.0.5b.)

@rattengift: Na ja, Regexps wie bei grep, sed und Konsorten sind es ja auch nicht, aber recht nah verwandt.

Was die Portabilität betrifft, bin ich gerade ins Schleudern gekommen. Auf älteren UNIX-Maschinen ist die Trennung recht strikt; es gibt dann halt grep mit Basic RegExps und egrep mit Extended Regexps (bei SCO OpenServer 3/5, beispielsweise). Auf einer Solaris 2.6 sagte mir die man-Page aber gerade, um portabel zu bleiben, solle man "/usr/xpg4/bin/grep -E" verwenden... Tja. grep und egrep gibt es aber weiterhin, wenn ggf. auch nur als 2 Links auf ein und dasselbe Programm. Ich nehme trotzdem erst mal meine Behauptung mit der Portabilität zurück und sage nur noch, dass ich es so machen würde. Kann sein, dass die moderneren Sys5R4.2-Unixe (und höher) da auch etwas vereinheitlicht haben.

Jochen

odo

Re: In bash auf Integer prüfen

#7 Post by odo »

Paßt gerade hierher:

Ist bei mehrfach ineinander geschachtelten if irgendwas zu beachten?
Ich bekomme dann immer ein "unexpected end of script" obwohl die if alle korrekt mit fi zu sind.

Was könnte das sein?

Jochen

Re: In bash auf Integer prüfen

#8 Post by Jochen »

"if" lässt sich beliebig schachteln. Wenn Du ein "Unexpected end of script" kriegst, dann ist es meistens ein fehlendes Anführungszeichen ("), ein fehlendes Apostroph ('), ein fehlender Backtick (`), eine fehlende schliessende geschweifte oder runde Klammer oder so etwas. Klammern kannst Du im vi sehr gut checken, wenn Du den Cursor auf eine Klammer stellst und dann "%" drückst. Der Cursor springt dann auf die dazu passende Klammer oder bleibt stehen, wenn er keine mehr dazu findet. Die anderen Zeichen musst Du händisch (äugisch?) prüfen.

Jochen

Post Reply