dumb question

I have a script which takes command line arguments. However I need to
check to makes sure if the arguments are numbers or not. What's the
easiest way?
joeytexeira [ So, 04 September 2005 19:45 ] [ ID #951925 ]

Re: dumb question

joeytexeira [at] mailinator.com wrote:

>
> I have a script which takes command line arguments. However I need to
> check to makes sure if the arguments are numbers or not. What's the
> easiest way?

What script language are you using?
matt_left_coast [ So, 04 September 2005 19:54 ] [ ID #951926 ]

Re: dumb question

On 2005-09-04, joeytexeira [at] mailinator.com wrote:
>
> I have a script which takes command line arguments. However I need to
> check to makes sure if the arguments are numbers or not. What's the
> easiest way?

How do you define "number"?

Is -2 a number? Is 1.23 a number? Is 1.23E8 a number? Is 0x12 a
number? All are valid numbers in some usages.

If a "number" give as as its argument contains only the digits 0
to 9 (i.e., is a postive integer), this function succeeds,
otherwise it fails:

is_num()
{
case $1 in
*[!0-9]*) return 5 ;;
esac
}

Then, to test whether a number is a positive integer:

is_num $NUM
if [ $? -ne 0 ]
then
echo "Not a positive integer"
exit 5
fi

To test for a positive or negative integer, remove any leading
minus sign when calling the function:

is_num ${NUM#-} ## requires a POSIX shell


--
Chris F.A. Johnson <http://cfaj.freeshell.org>
============================================================ ======
Shell Scripting Recipes: A Problem-Solution Approach, 2005, Apress
<http://www.torfree.net/~chris/books/cfaj/ssr.html>
cfajohnson [ So, 04 September 2005 20:07 ] [ ID #951927 ]

Re: Checking for a number. Was: "dumb question"

Assuming you use a shell like bash:

case $1 in
(*[^0-9]*) echo "Not pure digit string: $1"; exit;;
esac

uses only bash functionality.

echo -e "$1" | grep '^[0-9]+$' && echo "Yippiiii" || echo No...

does the same much slower. However, the grep regular expression can be
extended to include a period.

if echo -e "$1" | grep -E '^[0-9]+(\.[0-9]*)|\.[0-9]+$'
then echo "Whole number or decimal number"
else echo "Try something better"
fi

You could also include a sign:

echo -e "$1" | grep -E '^[-+]?([0-9]+(\.[0-9]*)|\.[0-9]+)$'

To handle numbers with exponents, like 1E6 (means 1000000), I first
tried to see if awk or perl would fail to understand the test string as
number, like this:

if perl -e "1 + $1" 2>/dev/null
then echo $1 is a number
else echo $1 is not a number
fi

This works quite nicely for malformed numbers with eg. two dots in
them. However, perl happily adds "1 + aa" (where "aa" is the string to
test) using the leading string of digits. That is, "1 + 23abc" becomes
24, and "1 + abc" becomes 1, just as "1 + 0abc". Awk, on the other
hand, assumes aa is a variable name and initializes it to zero.

A perl program to test for a number in a host of ways follows below.
You could delete the lines that do not interest you, and replace
"print..." with "exit 1" or "exit 0" as appropriate.

echo "$1" | perl -lne '
$n=3D0;
if (length) { print "$_" } else { print "The empty string" }
if (/\D/) { print " - has nondigits" }
if (/^\d+$/) { ++$n; print " - is a non-negative whole number"
}
if (/^-?\d+$/) { ++$n; print " - is an integer" }
if (/^[+-]?\d+$/) { ++$n; print " - is a +/- integer" }
if (/^-?\d+\.?\d*$/) { ++$n; print " - is a real number" }
if (/^-?(?:\d+(?:\.\d*)?=A6\.\d+)$/)
{ ++$n; print " - is a decimal number" }
if (/^[-+]?(?=3D\.?\d)\d*(\.\d*)?([Ee][-+]?\d+)?$/)
{ ++$n; print " - is a C float" }
if ($n =3D=3D 0) {print " - is not a number."}
'

Regards, Enrique
enrio [ Mo, 05 September 2005 01:01 ] [ ID #952673 ]

Re: Checking for a number. Was: "dumb question"

On 2005-09-04, enrio [at] online.no wrote:
> Assuming you use a shell like bash:
>
> case $1 in
> (*[^0-9]*) echo "Not pure digit string: $1"; exit;;
> esac

What do you know! I just learned something!

I was going to reply the the opening parenthesis was a mistake;
but I tried it and found that it worked. I checked the bash man
page and found that the opening parenthesis is optional; the POSIX
shell page says the same thing. I tried it with pdksh, ash, ksh93
and the Heirloom Bourne Shell, and it worked in all of them
(though not with the above code, which doesn't work in ksh).

I checked Steven Bourne's 1978 Introduction to the Unix Shell, and
it is not mentioned there, nor is it mentioned in my AT&T SysV/386
R3.2 sh man page. I'd be interested in knowing whether the older
Bourne shells support it or not.

> uses only bash functionality.

If you change the caret (^) to an exclamation mark (!), it will
work in all Bourne-type shells.

> echo -e "$1" | grep '^[0-9]+$' && echo "Yippiiii" || echo No...
>
> does the same much slower. However, the grep regular expression can be
> extended to include a period.
>
> if echo -e "$1" | grep -E '^[0-9]+(\.[0-9]*)|\.[0-9]+$'
> then echo "Whole number or decimal number"
> else echo "Try something better"
> fi

No need for grep:

case $1 in
*[!0-9.]* | *.*.* )
echo "Not a number: $1"
;;
*) echo "A number: $1" ;;
esac

> You could also include a sign:
>
> echo -e "$1" | grep -E '^[-+]?([0-9]+(\.[0-9]*)|\.[0-9]+)$'

No need for grep there, either:

case ${1#-} in
*[!0-9.]* | *.*.* )
echo "Not a number: $1"
;;
*) echo "A number: $1" ;;
esac

> To handle numbers with exponents, like 1E6 (means 1000000), I first
> tried to see if awk or perl would fail to understand the test string as
> number, like this:
>
> if perl -e "1 + $1" 2>/dev/null
> then echo $1 is a number
> else echo $1 is not a number
> fi

I've never needed to check for this, but perl (or awk) is not
necessary.


--
Chris F.A. Johnson <http://cfaj.freeshell.org>
============================================================ ======
Shell Scripting Recipes: A Problem-Solution Approach, 2005, Apress
<http://www.torfree.net/~chris/books/cfaj/ssr.html>
cfajohnson [ Mo, 05 September 2005 03:21 ] [ ID #952677 ]

Re: Checking for a number. Was: "dumb question"

Chris F.A. Johnson wrote:
> On 2005-09-04, enrio [at] online.no wrote:
>
>>Assuming you use a shell like bash:
>>
>> case $1 in
>> (*[^0-9]*) echo "Not pure digit string: $1"; exit;;
>> esac
>
>
> What do you know! I just learned something!
>
> I was going to reply the the opening parenthesis was a mistake;
> but I tried it and found that it worked. I checked the bash man
> page and found that the opening parenthesis is optional;

Though it is mandatory in ksh88 within a $(...) construct (according
to Bolsky/Korn).

Using the opening parenthesis prevents some editors to complain about
an unmatched bracket, BTW.

Janis
Janis Papanagnou [ Mo, 05 September 2005 03:38 ] [ ID #952678 ]

Re: Checking for a number. Was: "dumb question"

On 2005-09-05, Janis Papanagnou wrote:
> Chris F.A. Johnson wrote:
>> On 2005-09-04, enrio [at] online.no wrote:
>>
>>>Assuming you use a shell like bash:
>>>
>>> case $1 in
>>> (*[^0-9]*) echo "Not pure digit string: $1"; exit;;
>>> esac
>>
>>
>> What do you know! I just learned something!
>>
>> I was going to reply the the opening parenthesis was a mistake;
>> but I tried it and found that it worked. I checked the bash man
>> page and found that the opening parenthesis is optional;
>
> Though it is mandatory in ksh88 within a $(...) construct (according
> to Bolsky/Korn).
>
> Using the opening parenthesis prevents some editors to complain about
> an unmatched bracket, BTW.

Yes, I realized those two advantages to using the opening
parentheses at once.

--
Chris F.A. Johnson <http://cfaj.freeshell.org>
============================================================ ======
Shell Scripting Recipes: A Problem-Solution Approach, 2005, Apress
<http://www.torfree.net/~chris/books/cfaj/ssr.html>
cfajohnson [ Mo, 05 September 2005 03:56 ] [ ID #952680 ]

Re: Checking for a number. Was: "dumb question"

Janis Papanagnou wrote:
> Chris F.A. Johnson wrote:
>
>> On 2005-09-04, enrio [at] online.no wrote:
>>
>>> Assuming you use a shell like bash:
>>>
>>> case $1 in
>>> (*[^0-9]*) echo "Not pure digit string: $1"; exit;;
>>> esac
>>
>>
>>
>> What do you know! I just learned something!
>>
>> I was going to reply the the opening parenthesis was a mistake;
>> but I tried it and found that it worked. I checked the bash man
>> page and found that the opening parenthesis is optional;
>
>
> Though it is mandatory in ksh88 within a $(...) construct (according
> to Bolsky/Korn).

Could you give an example of the above? I must need another coffee or
something because I can't see how case statements and $(...) constructs
fit together....

Ed.
Ed Morton [ Mo, 05 September 2005 14:48 ] [ ID #952690 ]

Re: Checking for a number. Was: "dumb question"

On 2005-09-05, Chris F.A. Johnson <cfajohnson [at] gmail.com> wrote:
> On 2005-09-04, enrio [at] online.no wrote:
>> Assuming you use a shell like bash:
>>
>> case $1 in
>> (*[^0-9]*) echo "Not pure digit string: $1"; exit;;
>> esac
>
> What do you know! I just learned something!
>
> I was going to reply the the opening parenthesis was a mistake;
> but I tried it and found that it worked. I checked the bash man
> page and found that the opening parenthesis is optional; the POSIX
> shell page says the same thing. I tried it with pdksh, ash, ksh93
> and the Heirloom Bourne Shell, and it worked in all of them
> (though not with the above code, which doesn't work in ksh).
>
> I checked Steven Bourne's 1978 Introduction to the Unix Shell, and
> it is not mentioned there, nor is it mentioned in my AT&T SysV/386
> R3.2 sh man page. I'd be interested in knowing whether the older
> Bourne shells support it or not.

Open Unix 8.0 /bin/sh says "Syntax error at line n: `(' unexpected".
Solaris 8 /bin/sh says "syntax error at line n: `(' unexpected".

--
André Majorel <URL:http://www.teaser.fr/~amajorel/>
(Counterfeit: uveparud [at] construe.com edeneh [at] nostril.com)
"La presse doit diffuser des idées saines." -- Serge Dassault,
propriétaire de la Socpresse.
Andre Majorel [ Mo, 05 September 2005 17:51 ] [ ID #952695 ]

Re: Checking for a number. Was: "dumb question"

Ed Morton wrote:
> Janis Papanagnou wrote:
>> Chris F.A. Johnson wrote:
>>> On 2005-09-04, enrio [at] online.no wrote:
>>>
>>>> Assuming you use a shell like bash:
>>>>
>>>> case $1 in
>>>> (*[^0-9]*) echo "Not pure digit string: $1"; exit;;
>>>> esac
>>>
>>> What do you know! I just learned something!
>>>
>>> I was going to reply the the opening parenthesis was a mistake;
>>> but I tried it and found that it worked. I checked the bash man
>>> page and found that the opening parenthesis is optional;
>>
>> Though it is mandatory in ksh88 within a $(...) construct (according
>> to Bolsky/Korn).
>
> Could you give an example of the above? I must need another coffee or
> something because I can't see how case statements and $(...) constructs
> fit together....

Not sure whether this example or other examples like that "fits" any
practical needs...

print $( read inp;
case $inp in
42) print 1 ;;
*) print 0 ;;
esac )

....but as I understand the cited comment ksh88 (as opposed to ksh93)
might have produced a syntax error. It could be that the parsing has
been improved with ksh93. Someone with a ksh88 at hand might want to
verify that.

Janis
Janis Papanagnou [ Mo, 05 September 2005 21:41 ] [ ID #952699 ]
Linux » comp.unix.shell » dumb question

Vorheriges Thema: sed: looking for a string and replace a line (newbies question)
Nächstes Thema: Capitalising file names - is this possible with sed?