zsh-users
 help / color / mirror / code / Atom feed
* test if a parameter is numeric
@ 2007-02-09 17:05 zzapper
  2007-02-10  2:29 ` Bart Schaefer
  0 siblings, 1 reply; 16+ messages in thread
From: zzapper @ 2007-02-09 17:05 UTC (permalink / raw)
  To: zsh-users

Hi embarassingly elementary but its Friday

I just want to test if a parameter is numeric

if [ "$1" -gt '0' ] && [ "$1" -lt '9' ]
then

this works but barfs (but does not exit) if $1 is non-numeric

So what's the proper way to do this pls!

hey just solved it

if [[ "$1" == [0-9] ]]

I'll post anyway just in case some poor chump googles for this one day

-- 
zzapper
http://successtheory.com/tips/ Vim, Zsh, MySQL Tips


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: test if a parameter is numeric
  2007-02-09 17:05 test if a parameter is numeric zzapper
@ 2007-02-10  2:29 ` Bart Schaefer
  2007-02-10  8:35   ` Stephane Chazelas
  2007-02-10 18:13   ` Brian K. White
  0 siblings, 2 replies; 16+ messages in thread
From: Bart Schaefer @ 2007-02-10  2:29 UTC (permalink / raw)
  To: zsh-users

On Feb 9,  5:05pm, zzapper wrote:
}
} I just want to test if a parameter is numeric
} 
} if [[ "$1" == [0-9] ]]

Better:

  if [[ "$1" = <-> ]]

This is a zsh-ism, so it's not cross-shell portable, but the pattern <->
matches any string having any number of digits and only digits.


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: test if a parameter is numeric
  2007-02-10  2:29 ` Bart Schaefer
@ 2007-02-10  8:35   ` Stephane Chazelas
  2007-02-10 19:22     ` Bart Schaefer
  2007-02-10 18:13   ` Brian K. White
  1 sibling, 1 reply; 16+ messages in thread
From: Stephane Chazelas @ 2007-02-10  8:35 UTC (permalink / raw)
  To: zsh-users

On Fri, Feb 09, 2007 at 06:29:38PM -0800, Bart Schaefer wrote:
> On Feb 9,  5:05pm, zzapper wrote:
> }
> } I just want to test if a parameter is numeric
> } 
> } if [[ "$1" == [0-9] ]]
> 
> Better:
> 
>   if [[ "$1" = <-> ]]
> 
> This is a zsh-ism, so it's not cross-shell portable, but the pattern <->
> matches any string having any number of digits and only digits.

I was under the impression that zzapper was looking for
something to match *one* *decimal* digit though.

For positive decimal numbers, <-> will do (unless you don't want
to consider 09 or numbers greater than your max interger as
valid numbers).

To check for signed integer constants expressed in any notation
recognized by zsh (like 0xa, 8#77, 012 (being 10 or 12 depending
on "octalzeroes")...), it's a bit more tricky.

By the way, are those normal:

$ echo $((40#^))
39

(given that ^ is also an arithmetic operator)?

$ echo $((02#11))
3
$ setopt octalzeroes
$ echo $((02#11))
zsh: bad math expression: operator expected at `#11'
$

-- 
Stéphane


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: test if a parameter is numeric
  2007-02-10  2:29 ` Bart Schaefer
  2007-02-10  8:35   ` Stephane Chazelas
@ 2007-02-10 18:13   ` Brian K. White
  2007-02-10 18:31     ` Stephane Chazelas
                       ` (2 more replies)
  1 sibling, 3 replies; 16+ messages in thread
From: Brian K. White @ 2007-02-10 18:13 UTC (permalink / raw)
  To: zsh-users


----- Original Message ----- 
From: "Bart Schaefer" <schaefer@brasslantern.com>
To: <zsh-users@sunsite.dk>
Sent: Friday, February 09, 2007 9:29 PM
Subject: Re: test if a parameter is numeric


> On Feb 9,  5:05pm, zzapper wrote:
> }
> } I just want to test if a parameter is numeric
> }
> } if [[ "$1" == [0-9] ]]
>
> Better:
>
>  if [[ "$1" = <-> ]]
>
> This is a zsh-ism, so it's not cross-shell portable, but the pattern <->
> matches any string having any number of digits and only digits.

ksh, legacy sco/sun/etc  sh, bash etc...
I usually load the value into an integer typset variable,
sometimes testing the success/fail of the assignment itself:
    typeset -i N="$1" 2>/dev/null && echo yes || echo no
sometimes just using the resulting variable, treating "" different than "0" 
or the same as "0" depending on the situation
    typeset -i N="$1" 2>/dev/null
or if your shell has built in arithmatic (zsh/kash/bash, not plain sh on 
platforms where sh isn't really bash) instead of using a type defined 
variable, using the common age old trick (in any language) of just 
attempting an arithmatic operation, add 0 to the value.
    unset N
    N=$((1+0))
if $1 was numeric the N will have it, else N will still be unset

Both of the above approaches partially handle floating points.
The string may have a non-numerc "." in it, say "4.5" and the test will come 
out positive as numeric.
But, N will be "4" not 4.5 or 5

Depending on the source of the data, you may also want to run the string 
through tr -d "," so that 4,500 becomes 4500 and is treated as numeric.

Now someone will pipe up with some exotic 3 character zsh syntax thats like 
built-in sed on the fly instead of running a command like tr. "tr!! that's 
so 80's" heh :)

Brian K. White  --  brian@aljex.com  --  http://www.aljex.com/bkw/
+++++[>+++[>+++++>+++++++<<-]<-]>>+.>.+++++.+++++++.-.[>+<---]>++.
filePro  BBx    Linux  SCO  FreeBSD    #callahans  Satriani  Filk!


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: test if a parameter is numeric
  2007-02-10 18:13   ` Brian K. White
@ 2007-02-10 18:31     ` Stephane Chazelas
  2007-02-11  1:08     ` DervishD
       [not found]     ` <E1HG3Bl-0007Ge-DM@e4ward.com>
  2 siblings, 0 replies; 16+ messages in thread
From: Stephane Chazelas @ 2007-02-10 18:31 UTC (permalink / raw)
  To: Brian K. White; +Cc: zsh-users

On Sat, Feb 10, 2007 at 01:13:57PM -0500, Brian K. White wrote:
[...]
>    typeset -i N="$1" 2>/dev/null
> or if your shell has built in arithmatic (zsh/kash/bash, not plain sh on 
> platforms where sh isn't really bash) instead of using a type defined 
> variable, using the common age old trick (in any language) of just 
> attempting an arithmatic operation, add 0 to the value.
>    unset N
>    N=$((1+0))
> if $1 was numeric the N will have it, else N will still be unset
[...]

Those approaches will say that "1+1", "a=1", "SECONDS"... are
numbers some with potentially nasty side effects, as for $1 ==
"PATH=0", 

$ set 'PATH=0'
$ N=$(($1+0))
$ ls
ls:2: command not found: ls

-- 
Stéphane


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: test if a parameter is numeric
  2007-02-10  8:35   ` Stephane Chazelas
@ 2007-02-10 19:22     ` Bart Schaefer
  2007-02-10 20:38       ` Stephane Chazelas
  0 siblings, 1 reply; 16+ messages in thread
From: Bart Schaefer @ 2007-02-10 19:22 UTC (permalink / raw)
  To: zsh-users

On Feb 10,  8:35am, Stephane Chazelas wrote:
} Subject: Re: test if a parameter is numeric
}
} On Fri, Feb 09, 2007 at 06:29:38PM -0800, Bart Schaefer wrote:
} > On Feb 9,  5:05pm, zzapper wrote:
} > }
} > } I just want to test if a parameter is numeric
} 
} I was under the impression that zzapper was looking for
} something to match *one* *decimal* digit though.

He said "numeric", but you may be right.
 
} By the way, are those normal:
} 
} $ echo $((40#^))
} 39
} 
} (given that ^ is also an arithmetic operator)?

% typeset -i 40 x
% x=39
% echo $x
40#^

Zsh is choosing "^" to represent 39 in base 40 because carat is the 29th
ASCII character after capital A, so the base 40 "digits" are
    0123456789ABC...XYZ[\]^

Some pretty strange stuff happens with bases larger than 200 where the
available range of "digits" runs out.  There should probably at least be
a warning about that somewhere.

There's definitely some other funny parsing going on here:

% echo $((##v)) 
118
% echo $((##0))
48
% echo $((##v - ##0))
70
% echo $((##^))      
94
% echo $((##^ - ##0))
-48
% echo $(((##v) - (##0)))    
70
% echo $(((##^) - (##0)))
zsh: ')' expected
% echo $[ $((##^)) - $((##0)) ]
46

} $ echo $((02#11))
} 3
} $ setopt octalzeroes
} $ echo $((02#11))
} zsh: bad math expression: operator expected at `#11'
} $
} 
} -- 
} Stéphane
}-- End of excerpt from Stephane Chazelas



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: test if a parameter is numeric
  2007-02-10 19:22     ` Bart Schaefer
@ 2007-02-10 20:38       ` Stephane Chazelas
  0 siblings, 0 replies; 16+ messages in thread
From: Stephane Chazelas @ 2007-02-10 20:38 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: zsh-users

On Sat, Feb 10, 2007 at 11:22:35AM -0800, Bart Schaefer wrote:
[...]
> % typeset -i 40 x
> % x=39
> % echo $x
> 40#^
> 
> Zsh is choosing "^" to represent 39 in base 40 because carat is the 29th
> ASCII character after capital A, so the base 40 "digits" are
>     0123456789ABC...XYZ[\]^
[...]

Hi,

apparently, only the 5 lower bits matter as I found out, that's
why $((40#^)) is the same as $((40#~))



[...]
> % echo $((##^))      
> 94
[...]

Here:

$ echo $((##^))
0

(zsh 4.3.2 from debian package 4.3.2-25)

zsh 4.3.2-dev-1+20070206-1 is OK though.

37 is $((40#\\))

-- 
Stéphane


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: test if a parameter is numeric
  2007-02-10 18:13   ` Brian K. White
  2007-02-10 18:31     ` Stephane Chazelas
@ 2007-02-11  1:08     ` DervishD
       [not found]     ` <E1HG3Bl-0007Ge-DM@e4ward.com>
  2 siblings, 0 replies; 16+ messages in thread
From: DervishD @ 2007-02-11  1:08 UTC (permalink / raw)
  To: Brian K. White; +Cc: zsh-users

    Hi Brian :)

 * Brian K. White <brian@aljex.com> dixit:
> 
> ----- Original Message ----- 
> From: "Bart Schaefer" <schaefer@brasslantern.com>
> To: <zsh-users@sunsite.dk>
> Sent: Friday, February 09, 2007 9:29 PM
> Subject: Re: test if a parameter is numeric
> 
> 
> >On Feb 9,  5:05pm, zzapper wrote:
> >}
> >} I just want to test if a parameter is numeric
> >}
> >} if [[ "$1" == [0-9] ]]
> >
> >Better:
> >
> > if [[ "$1" = <-> ]]
> >
> >This is a zsh-ism, so it's not cross-shell portable, but the pattern <->
> >matches any string having any number of digits and only digits.
> 
> ksh, legacy sco/sun/etc  sh, bash etc...

    If you can use "expr", you can do it with "expr", using simple
regexes. OK, not the fastest method, but should do and should do it
pretty fast. I use this approach in my "mobs" project. Being bulletproof
using almost-portable shell scripting is, at least, tricky. And probably
impossible, for what I've seen...

    Raúl Núñez de Arenas Coronado

-- 
Linux Registered User 88736 | http://www.dervishd.net
It's my PC and I'll cry if I want to... RAmen!


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: test if a parameter is numeric
       [not found]     ` <E1HG3Bl-0007Ge-DM@e4ward.com>
@ 2007-02-20  0:14       ` Lydgate
  2007-02-20  3:21         ` Andrew Ruder
                           ` (3 more replies)
  0 siblings, 4 replies; 16+ messages in thread
From: Lydgate @ 2007-02-20  0:14 UTC (permalink / raw)
  To: zsh-users

On Sun, Feb 11, 2007 at 02:08:40AM +0100, DervishD wrote:
>     If you can use "expr", you can do it with "expr", using simple
> regexes. OK, not the fastest method, but should do and should do it
> pretty fast. I use this approach in my "mobs" project. Being bulletproof
> using almost-portable shell scripting is, at least, tricky. And probably
> impossible, for what I've seen...
> 
>     Raúl Núñez de Arenas Coronado

Sorry maybe I'm missing something, but if you need to match more than
one digit, what's wrong with:

[[ "$1" == [0-9][0-9]* ]]

Which I think is more portable?

Lydgate


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: test if a parameter is numeric
  2007-02-20  0:14       ` Lydgate
@ 2007-02-20  3:21         ` Andrew Ruder
       [not found]         ` <E1HJLZy-0001UA-44@b.e4ward.com>
                           ` (2 subsequent siblings)
  3 siblings, 0 replies; 16+ messages in thread
From: Andrew Ruder @ 2007-02-20  3:21 UTC (permalink / raw)
  To: zsh-users

On Tue, Feb 20, 2007 at 12:14:55AM +0000, Lydgate wrote:
> Sorry maybe I'm missing something, but if you need to match more than
> one digit, what's wrong with:
> 
> [[ "$1" == [0-9][0-9]* ]]

Lydgate,

shell script expressions != regex expressions.  The expression up there
would match:

00
01
02
03abc

but not:

1
2
3

However, I will give you that your expression would work fine in a regex
engine...

There is a ZSH extension that would have more of the effect you are
looking for but its as unportable as most other solutions,
unfortunately.

- Andy

-- 
Andrew Ruder <andy@aeruder.net>
http://www.aeruder.net


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: test if a parameter is numeric
       [not found]         ` <E1HJLZy-0001UA-44@b.e4ward.com>
@ 2007-02-20  3:56           ` zsh
  0 siblings, 0 replies; 16+ messages in thread
From: zsh @ 2007-02-20  3:56 UTC (permalink / raw)
  To: zsh-users

On Mon, Feb 19, 2007 at 09:21:38PM -0600, Andrew Ruder wrote:
> There is a ZSH extension that would have more of the effect you are
> looking for but its as unportable as most other solutions,
> unfortunately.

Ah, okay.  What I was thinking of is a bashism anyway:

[[ "$1" =~ [0-9][0-9]*$ ]]

I forgot it should be =~, and the $ will prevent it from matching your
other examples.  But this seems to mean something else in zsh.

Lydgate


^ permalink raw reply	[flat|nested] 16+ messages in thread

* RE: test if a parameter is numeric
  2007-02-20  0:14       ` Lydgate
  2007-02-20  3:21         ` Andrew Ruder
       [not found]         ` <E1HJLZy-0001UA-44@b.e4ward.com>
@ 2007-02-20  7:02         ` Com MN PG P E B Consultant 3
  2007-02-20  7:52         ` DervishD
  3 siblings, 0 replies; 16+ messages in thread
From: Com MN PG P E B Consultant 3 @ 2007-02-20  7:02 UTC (permalink / raw)
  To: Lydgate, zsh-users

> Sorry maybe I'm missing something, but if you need to match more than
> one digit, what's wrong with:
> 
> [[ "$1" == [0-9][0-9]* ]]

Because it would also match "35X". Note that we have glob pattern here,
not regular expressions.

Ronald
-- 
Ronald Fischer (phone +49-89-63676431)
mailto:mn-pg-p-e-b-consultant-3.com@siemens.com


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: test if a parameter is numeric
  2007-02-20  0:14       ` Lydgate
                           ` (2 preceding siblings ...)
  2007-02-20  7:02         ` Com MN PG P E B Consultant 3
@ 2007-02-20  7:52         ` DervishD
  2007-02-20 14:35           ` Frank Terbeck
  2007-02-20 20:20           ` Stephane Chazelas
  3 siblings, 2 replies; 16+ messages in thread
From: DervishD @ 2007-02-20  7:52 UTC (permalink / raw)
  To: Lydgate; +Cc: zsh-users

    Hi Lydgate :)

 * Lydgate <zsh@lydgate.e4ward.com> dixit:
> On Sun, Feb 11, 2007 at 02:08:40AM +0100, DervishD wrote:
> >     If you can use "expr", you can do it with "expr", using simple
> > regexes. OK, not the fastest method, but should do and should do it
> > pretty fast. I use this approach in my "mobs" project. Being bulletproof
> > using almost-portable shell scripting is, at least, tricky. And probably
> > impossible, for what I've seen...
> 
> Sorry maybe I'm missing something, but if you need to match more than
> one digit, what's wrong with:
> 
> [[ "$1" == [0-9][0-9]* ]]
> 
> Which I think is more portable?

    If you are considering the second part as a regex, then the above is
definitely NON portable. It's not even POSIX.

    But the second part is not a regex, but a shell globbing pattern.
That means that the above will match something like "1234abcd", for
example, and ONLY if the file exists. Otherwise it won't match anything.

    In addition to this, if the expansion is not successful, some shells
may substitute nothing in the second part, leaving you with the invalid
construct:

    [[ "$1" == ]]

    And the "[[" is NOT portable, either, it's a zsh thing (and probably
bash has too, I don't know, but AFAIK is not POSIX/SuS).

    Raúl Núñez de Arenas Coronado

-- 
Linux Registered User 88736 | http://www.dervishd.net
It's my PC and I'll cry if I want to... RAmen!


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: test if a parameter is numeric
  2007-02-20  7:52         ` DervishD
@ 2007-02-20 14:35           ` Frank Terbeck
  2007-02-20 20:20           ` Stephane Chazelas
  1 sibling, 0 replies; 16+ messages in thread
From: Frank Terbeck @ 2007-02-20 14:35 UTC (permalink / raw)
  To: zsh-users; +Cc: Lydgate

DervishD <zsh@dervishd.net>:
> Lydgate <zsh@lydgate.e4ward.com> dixit:
> > On Sun, Feb 11, 2007 at 02:08:40AM +0100, DervishD wrote:
> > >     If you can use "expr", you can do it with "expr", using simple
> > > regexes. OK, not the fastest method, but should do and should do it
> > > pretty fast. I use this approach in my "mobs" project. Being bulletproof
> > > using almost-portable shell scripting is, at least, tricky. And probably
> > > impossible, for what I've seen...
> > 
> > Sorry maybe I'm missing something, but if you need to match more than
> > one digit, what's wrong with:
> > 
> > [[ "$1" == [0-9][0-9]* ]]
> > 
> > Which I think is more portable?
> 
>     If you are considering the second part as a regex, then the above is
> definitely NON portable. It's not even POSIX.
[...]
>     And the "[[" is NOT portable, either, it's a zsh thing (and probably
> bash has too, I don't know, but AFAIK is not POSIX/SuS).

"[[" was introduced by ksh, AFAIK.
And you are right, it's not SUSv3.
To check whether a variable contains only digits, how about this:

[snip]
if [ -n "${var}" ] && [ "${var}" = "${var%%[!0-9]*}" ] ; then
  echo "\$var holds a numeric value"
fi
[snap]

This should work in all shells that support SUSv3 syntax. It will
break in original bourne-type shells (like /bin/sh in opensolaris,
IIRC), because they do not understand ${var%%pattern} and the like.

Regards, Frank

-- 
In protocol design, perfection has been reached not when there is
nothing left to add, but when there is nothing left to take away.
                                                  -- RFC 1925


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: test if a parameter is numeric
  2007-02-20  7:52         ` DervishD
  2007-02-20 14:35           ` Frank Terbeck
@ 2007-02-20 20:20           ` Stephane Chazelas
  2007-02-20 21:35             ` Stephane Chazelas
  1 sibling, 1 reply; 16+ messages in thread
From: Stephane Chazelas @ 2007-02-20 20:20 UTC (permalink / raw)
  To: Lydgate, zsh-users

On Tue, Feb 20, 2007 at 08:52:26AM +0100, DervishD wrote:
[...]
>     [[ "$1" == ]]
> 
>     And the "[[" is NOT portable, either, it's a zsh thing (and probably
> bash has too, I don't know, but AFAIK is not POSIX/SuS).
[...]

rather from ksh.

POSIXly, you'd write

case $1 in
  ("" | *[!0-9]) echo not a number;;
  (*) echo is a number;;
esac

The equivalent of bash's [[ ... =~ ... ]]
is [[ ... -pcre-match ... ]] which uses perl compatible
regexps.

Note that zsh extended globbing patterns, though with a
different syntax are functionnaly equivalent to regexps and has
may additions over it.

ERE -> zsh
.      ?
*      #
+      ##
?      (|...)
(...)  (...)
(..|..)(..|..)

So

[[ $1 == [0-9]## ]]

-- 
Stéphane


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: test if a parameter is numeric
  2007-02-20 20:20           ` Stephane Chazelas
@ 2007-02-20 21:35             ` Stephane Chazelas
  0 siblings, 0 replies; 16+ messages in thread
From: Stephane Chazelas @ 2007-02-20 21:35 UTC (permalink / raw)
  To: Lydgate, zsh-users

On Tue, Feb 20, 2007 at 08:20:01PM +0000, Stephane Chazelas wrote:
> On Tue, Feb 20, 2007 at 08:52:26AM +0100, DervishD wrote:
> [...]
> >     [[ "$1" == ]]
> > 
> >     And the "[[" is NOT portable, either, it's a zsh thing (and probably
> > bash has too, I don't know, but AFAIK is not POSIX/SuS).
> [...]
> 
> rather from ksh.
> 
> POSIXly, you'd write
> 
> case $1 in
>   ("" | *[!0-9]) echo not a number;;

   ("" | *[!0-9]*) echo not a number;;

sorry.

[...]
> Note that zsh extended globbing patterns, though with a
> different syntax are functionnaly equivalent to regexps and has
> may additions over it.
> 
> ERE -> zsh
> .      ?
> *      #
> +      ##
> ?      (|...)
> (...)  (...)
> (..|..)(..|..)
[...]

It can also be said of ksh's globs (same as bash with extglob or
zsh with kshglob)

ERE -> ksh
.      ?
a*     *(a)
a+     +(a)
a?     ?(a)
(a|b)  @(a|b)

recent versions of ksh have more features. There are features in
ksh globs that are not available in zsh's ones like {3}(...),
and likewise in the other direction like <1-10>.

ksh's @(a*b&*c*) can be written in zsh: a*b~^*c* (and not not),
I don't think bash has an equivalent

-- 
Stéphane


^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2007-02-20 21:36 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-02-09 17:05 test if a parameter is numeric zzapper
2007-02-10  2:29 ` Bart Schaefer
2007-02-10  8:35   ` Stephane Chazelas
2007-02-10 19:22     ` Bart Schaefer
2007-02-10 20:38       ` Stephane Chazelas
2007-02-10 18:13   ` Brian K. White
2007-02-10 18:31     ` Stephane Chazelas
2007-02-11  1:08     ` DervishD
     [not found]     ` <E1HG3Bl-0007Ge-DM@e4ward.com>
2007-02-20  0:14       ` Lydgate
2007-02-20  3:21         ` Andrew Ruder
     [not found]         ` <E1HJLZy-0001UA-44@b.e4ward.com>
2007-02-20  3:56           ` zsh
2007-02-20  7:02         ` Com MN PG P E B Consultant 3
2007-02-20  7:52         ` DervishD
2007-02-20 14:35           ` Frank Terbeck
2007-02-20 20:20           ` Stephane Chazelas
2007-02-20 21:35             ` Stephane Chazelas

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).