Puppy Linux Discussion Forum Forum Index Puppy Linux Discussion Forum
Puppy HOME page : puppylinux.com
"THE" alternative forum : puppylinux.info
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

The time now is Sat 18 Aug 2018, 03:08
All times are UTC - 4
 Forum index » Off-Topic Area » Programming
A simple way to detect an odd or even number in bash
Post new topic   Reply to topic View previous topic :: View next topic
Page 2 of 2 [26 Posts]   Goto page: Previous 1, 2
Author Message
technosaurus


Joined: 18 May 2008
Posts: 4829
Location: Kingwood, TX

PostPosted: Thu 22 Feb 2018, 23:09    Post subject:  

MochiMoppel wrote:
For a bullet proof check this should do:
Code:
[[ $N =~ ^-?[0-9]+$ ]] || exec echo $N is not an integer

for a non bashism version (as long as parameters don't contain spaces)
Code:
isnumber() [[ $(($1+0)) = ${1} ]]

_________________
Check out my github repositories. I may eventually get around to updating my blogspot.
Back to top
View user's profile Send private message Visit poster's website 
musher0


Joined: 04 Jan 2009
Posts: 12570
Location: Gatineau (Qc), Canada

PostPosted: Thu 22 Feb 2018, 23:25    Post subject:  

MochiMoppel wrote:
@musher0: Your original idea to use a case statement wasn't bad. While checking
only the last digit doesn't tell you if you are dealing with an integer, you could easily
adapt your case conditions to allow only integers and issue a warning if none of the
conditions match. In the end such construct is not more complex than using bash
arithmetic operators and doesn't require knowledge on how modulo or bash division
work.

Using modulo and bash:
Code:
[[ $N = *[^0-9-]* ]] && echo $N is not an integer && exit
(($N%2)) && echo $N is odd ||  echo $N is even
Note: The integer check avoids regex, but it doesn't catch oddly placed minus signs.

For a bullet proof check this should do:
Code:
[[ $N =~ ^-?[0-9]+$ ]] || exec echo $N is not an integer
.

Hello MochiMopei.

As I said above, I evolved this idea in the context of a list of files that I needed to
split in two "halves" (+/- one line) with head and tail. Now wc -l does not care if the
last line is only half full or a quarter full!! It was not even a text, just a list of files.
I did not need to check for decimals except if the total of lines is odd.

I am a man of the field, not a theorist. I respond to practical situations I encounter.
I was not expecting to have so many replies! But you guys with more knowledge
than me, please continue; this discussion has become most interesting.

Bye for now.

~~~~~~~~~~~~~~
Sorry to disappoint everyone (!), but this is the script where I originally encountered
this odd/even problem:
Code:
#!/bin/sh
# ~/.pekwm/defaults-pekwm.sh
#
# Goal: create a pekwm sub-menu in two +/- equal parts for Puppy's' /usr/local/bin/default* files.
#
# © Christian L'Écuyer, Gatineau (Qc), Canada, 2018/02/18. GPL3
# (Alias musher0 [forum Puppy].) # Rév. : 2018/02/20
#################   # https://opensource.org/licenses/GPL-3.0
#    This program is free software: you can redistribute it and/or modify it under the
#    terms of the GNU General Public License as published by the Free Software
#    Foundation, either version 3 of the License, or  (at your option) any later version.
#         This program is distributed in the hope that it will be useful, but WITHOUT ANY
#    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
#    A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#         You should have received a copy of the GNU General Public License along with
#   this program. If not, see <http://www.gnu.org/licenses/>.
##########
#   Ce programme est libre : vous pouvez le redistribuer ou modifier selon les termes
#   de la Licence Publique Générale GNU publiée par la Free Software Foundation (v. 3
#   ou toute version ultérieure choisie par vous).
#       Ce programme est distribué dans l'espoir qu'il sera utile, mais SANS AUCUNE
#   GARANTIE, ni explicite ni implicite, y compris des garanties de commercialisation
#   ou d'adaptation à un but spécifique. Pour plus de détails, veuillez vous reporter
#   au texte officiel de cette licence à https://opensource.org/licenses/GPL-3.0, à
#   http://www.linux-france.org/article/these/gpl.html pour une traduction et, pour une
#   explication en français, à https://fr.wikipedia.org/wiki/Licence_publique_générale_GNU.
################
#### set -xe
cd ~/.pekwm
LC_ALL=C
ProgLine () { echo -e "\t\tEntry = \"${line#*t}\" { Actions = \"Exec $line &\" }" >> ~/.pekwm/menu.Defaults.tmp2; }

AppS=/usr/local/bin
cd $AppS
ls -Algo default* | awk '$1 !~ /lrw/ && $NF !~ /lts-|run|cdr|handler/ { print $NF }' > ~/.pekwm/default-progs

echo "}
# Ferme le sous-menu précédent." > ~/.pekwm/menu.Defaults

case "${LANG:0:2}" in
     fr)echo "Submenu = \"Applis par défaut\" {" >> ~/.pekwm/menu.Defaults ;;
     en|*)echo "Submenu = \"Default Apps\" {" >> ~/.pekwm/menu.Defaults ;;
esac

> ~/.pekwm/menu.Defaults.tmp2
while read line;do ProgLine;done < ~/.pekwm/default-progs
case "${LANG:0:2}" in
     fr) # Il est plus pratique de traduire avant de faire la division.
          RPLCT="replaceit --input=/root/.pekwm/menu.Defaults.tmp2"
$RPLCT archiver archiveur "}default" "{Entry";$RPLCT audiomixer mixeur "}default" "{Entry"
$RPLCT browser navigateur "}default" "{Entry";$RPLCT calendar calendrier "}default" "{Entry"
$RPLCT chat clavardage "}default" "{Entry";$RPLCT connect connexion "}default" "{Entry"
$RPLCT draw "ed. de dessin" "}default" "{Entry";$RPLCT email courriel "}default" "{Entry"
$RPLCT paint "ed. d'image" "}default" "{Entry";$RPLCT screenshot captures "}default" "{Entry"
$RPLCT spreadsheet chiffrier "}default" "{Entry";$RPLCT audioeditor "ed. audio" "}default" "{Entry"
$RPLCT audioplayer "lect. audio" "}default" "{Entry";$RPLCT cdplayer "lect. CD" "}default" "{Entry"
$RPLCT cdrecorder enregistreur "}default" "{Entry";$RPLCT chmviewer "vis. de chm" "}default" "{Entry"
$RPLCT filemanager "gest. de fich." "}default" "{Entry";$RPLCT htmleditor "ed. de html" "}default" "{Entry"
$RPLCT pdfviewer "vis. de pdf" "}default\"" "{Entry";$RPLCT htmlviewer "vis. de html" "}default" "{Entry"
$RPLCT imageviewer "vis. d'image" "}default" "{Entry";$RPLCT mediaplayer "lect. media" "}default" "{Entry"
$RPLCT processmanager "gest. de proc." "}default" "{Entry"
$RPLCT texteditor "ed. de texte" "}default" "{Entry";$RPLCT textviewer "vis. de texte" "}default" "{Entry"
$RPLCT wordprocessor "tr. de texte" "}default" "{Entry"
          sort ~/.pekwm/menu.Defaults.tmp2 > ~/.pekwm/menu.Defaults.tmp ;; # Tri nécessaire
     en|*)
          mv ~/.pekwm/menu.Defaults.tmp2 ~/.pekwm/menu.Defaults.tmp ;;
esac
echo "Submenu = \"1...\" {" >> ~/.pekwm/menu.Defaults

# Vérifier si nlign est impair.
nlign="`cat ~/.pekwm/menu.Defaults.tmp | wc -l`"
case "${nlign: -1}" in # Si nombre impair, on aura un tuilage dans les entrées, # ;-) to MochiMoppei!
     1|3|5|7|9)nlign="`expr $nlign + 1`" ;;
esac
nlign="`expr $nlign \/ 2`" # mais on peut alors diviser sans reste.
#
head -n "$nlign"  /root/.pekwm/menu.Defaults.tmp >> ~/.pekwm/menu.Defaults
echo -e "\t}" >> ~/.pekwm/menu.Defaults
echo "Submenu = \"2...\" {" >> ~/.pekwm/menu.Defaults
tail -n "$nlign"  /root/.pekwm/menu.Defaults.tmp >> ~/.pekwm/menu.Defaults
echo -e "\t}\n}" >> ~/.pekwm/menu.Defaults

rm -f ~/.pekwm/menu.Defaults.tmp*
rm -f ~/.pekwm/default-progs

LC_ALL="" # set +xe

Scrots of the results are attached.

Also, these are the submenus (English version) that the above script creates,
which are read by the pekwm menu routine:
Code:
}
# Ferme le sous-menu précédent.
Submenu = "Default Apps" {
Submenu = "1..." {
      Entry = "archiver" { Actions = "Exec defaultarchiver &" }
      Entry = "audioeditor" { Actions = "Exec defaultaudioeditor &" }
      Entry = "audiomixer" { Actions = "Exec defaultaudiomixer &" }
      Entry = "audioplayer" { Actions = "Exec defaultaudioplayer &" }
      Entry = "browser" { Actions = "Exec defaultbrowser &" }
      Entry = "calendar" { Actions = "Exec defaultcalendar &" }
      Entry = "cdplayer" { Actions = "Exec defaultcdplayer &" }
      Entry = "chat" { Actions = "Exec defaultchat &" }
      Entry = "chmviewer" { Actions = "Exec defaultchmviewer &" }
      Entry = "connect" { Actions = "Exec defaultconnect &" }
      Entry = "contact" { Actions = "Exec defaultcontact &" }
      Entry = "draw" { Actions = "Exec defaultdraw &" }
      Entry = "email" { Actions = "Exec defaultemail &" }
      Entry = "filemanager" { Actions = "Exec defaultfilemanager &" }
   }
Submenu = "2..." {
      Entry = "filemanager" { Actions = "Exec defaultfilemanager &" }
      Entry = "htmleditor" { Actions = "Exec defaulthtmleditor &" }
      Entry = "htmlviewer" { Actions = "Exec defaulthtmlviewer &" }
      Entry = "imageviewer" { Actions = "Exec defaultimageviewer &" }
      Entry = "mediaplayer" { Actions = "Exec defaultmediaplayer &" }
      Entry = "paint" { Actions = "Exec defaultpaint &" }
      Entry = "pdfviewer" { Actions = "Exec defaultpdfviewer &" }
      Entry = "processmanager" { Actions = "Exec defaultprocessmanager &" }
      Entry = "screenshot" { Actions = "Exec defaultscreenshot &" }
      Entry = "spreadsheet" { Actions = "Exec defaultspreadsheet &" }
      Entry = "terminal" { Actions = "Exec defaultterminal &" }
      Entry = "texteditor" { Actions = "Exec defaulttexteditor &" }
      Entry = "textviewer" { Actions = "Exec defaulttextviewer &" }
      Entry = "wordprocessor" { Actions = "Exec defaultwordprocessor &" }
   }
}
pekwm-submenu-1-for-defaults.jpg
 Description   
 Filesize   94.67 KB
 Viewed   266 Time(s)

pekwm-submenu-1-for-defaults.jpg

pekwm-submenu-2-for-defaults.png
 Description   The overlap is intentional, between the first entry of this one and the last entry of the first one. ("Gest. de fich." is abbreviated French for "filemanager".)
 Filesize   55.32 KB
 Viewed   259 Time(s)

pekwm-submenu-2-for-defaults.png


_________________
musher0
~~~~~~~~~~
Siempre será canción nueva... (V. Jara, Manifiesto)

Last edited by musher0 on Fri 23 Feb 2018, 00:57; edited 3 times in total
Back to top
View user's profile Send private message 
MochiMoppel


Joined: 26 Jan 2011
Posts: 1579
Location: Japan

PostPosted: Thu 22 Feb 2018, 23:50    Post subject:  

musher0 wrote:
I am a man of the field, not a theorist. I respond to practical situations I encounter.
I was trying to defend your solution, not dismiss it.
Back to top
View user's profile Send private message 
musher0


Joined: 04 Jan 2009
Posts: 12570
Location: Gatineau (Qc), Canada

PostPosted: Thu 22 Feb 2018, 23:52    Post subject:  

MochiMoppel wrote:
musher0 wrote:
I am a man of the field, not a theorist. I respond to practical situations I encounter.
I was trying to defend your solution, not dismiss it.
I know! And I thank you for it.
_________________
musher0
~~~~~~~~~~
Siempre será canción nueva... (V. Jara, Manifiesto)
Back to top
View user's profile Send private message 
MochiMoppel


Joined: 26 Jan 2011
Posts: 1579
Location: Japan

PostPosted: Fri 23 Feb 2018, 01:38    Post subject:  

technosaurus wrote:
for a non bashism version (as long as parameters don't contain spaces)
Code:
isnumber() [[ $(($1+0)) = ${1} ]]
AFAIK double brackets are not POSIX compliant though bash supports them also in its "more closely to the POSIX standard" mode.
Back to top
View user's profile Send private message 
technosaurus


Joined: 18 May 2008
Posts: 4829
Location: Kingwood, TX

PostPosted: Fri 23 Feb 2018, 01:49    Post subject:  

MochiMoppel wrote:
technosaurus wrote:
for a non bashism version (as long as parameters don't contain spaces)
Code:
isnumber() [[ $(($1+0)) = ${1} ]]
AFAIK double brackets are not POSIX compliant though bash supports them also in its "more closely to the POSIX standard" mode.
crap, you are right, always get that backwards - it should still work if you change them to single brackets as long as the parameters are quoted or don't contain spaces, newlines or tabs. FWIW both busybox shells (ash and hush) support both forms.
_________________
Check out my github repositories. I may eventually get around to updating my blogspot.
Back to top
View user's profile Send private message Visit poster's website 
MochiMoppel


Joined: 26 Jan 2011
Posts: 1579
Location: Japan

PostPosted: Fri 23 Feb 2018, 03:40    Post subject:  

technosaurus wrote:
it should still work if you change them to single brackets as long as the parameters are quoted or don't contain spaces, newlines or tabs

No, it does not work
- A single bracket is an ordinary command. The function requires curly braces.
- $(($1+0)) will generate an irrecoverable syntax error if the parameter contains a decimal separator, which makes this test unsuitable as an integer check. Same happens with double brackets.

The following code should work better. Spaces etc. in parameters will lead to a correct "not an integer" result
Decimal separators will not generate a fatal syntax error.
Code:
isnumber() { test "$@" -eq "$@"  2>/dev/null ;}
Back to top
View user's profile Send private message 
technosaurus


Joined: 18 May 2008
Posts: 4829
Location: Kingwood, TX

PostPosted: Fri 23 Feb 2018, 12:11    Post subject:  

MochiMoppel wrote:
The function requires curly braces.
It can be any compound statement which also includes a subshell "( ... )" in Posix and "[[ ... ]]" in bash, ksh (since 1988) and any modern shell including busybox and just about everything but dash. I didn't realize that even with "{ ... }", the compound statement can also be followed by redirection of stdin, stdout, stderr (useful for logging). The double bracket version does have some subtle differences though. I seem to have gotten a bit rusty on my shell programming. Likely because I have been using C primarily for the last few years and mostly awk right before that. Perhaps I should write myself a manual as I relearn it for the next time I forget. Tentatively titled "The Portable Shell Scripting Guide" as an answer to "The Advanced Bash Scripting Guide" ... DashAsBinSh mainly describes pitfalls without offering solutions
_________________
Check out my github repositories. I may eventually get around to updating my blogspot.
Back to top
View user's profile Send private message Visit poster's website 
NeroVance


Joined: 10 Oct 2012
Posts: 196
Location: Halifax, Canada

PostPosted: Mon 02 Apr 2018, 08:17    Post subject:  

musher0 wrote:
puppy_apprentice wrote:
When i was learning Pascal in high school i was using this formula before i noticed that Pascal has odd function built-in.
Code:

#!/bin/sh
check=`expr $1 / 2 \* 2`
if [ $check != $1 ]
then
  echo "$1 is odd"
else
  echo "$1 is even"
fi
You learned Pascal in high school? You must be very old?!?! Laughing

Oddly enough I'm only 24, but my older sister learned Pascal in High School from what I recall.
Back to top
View user's profile Send private message 
musher0


Joined: 04 Jan 2009
Posts: 12570
Location: Gatineau (Qc), Canada

PostPosted: Mon 02 Apr 2018, 09:35    Post subject:  

That's funny. Being 24 is not odd! Very Happy Being 24 is being young!

I was saying that because Pascal is an old computer language,
as computer languages go.

_________________
musher0
~~~~~~~~~~
Siempre será canción nueva... (V. Jara, Manifiesto)
Back to top
View user's profile Send private message 
jafadmin

Joined: 19 Mar 2009
Posts: 833

PostPosted: Mon 02 Apr 2018, 16:53    Post subject:  

Check the least significant bit: ((($MyVal&1)==0))

Code:
  MyVal=221;((($MyVal&1)==0)) && echo "$MyVal is even" || echo "$MyVal is odd"

Or ...
Code:
if (($MyVal&1))
then    echo "$MyVal is odd"
else    echo "$MyVal is even"
fi

In C:
Code:
int MyVal = 332;
printf( "Value of MyVal is %s\n", (MyVal&1) ? "odd": "even" );
Back to top
View user's profile Send private message 
Display posts from previous:   Sort by:   
Page 2 of 2 [26 Posts]   Goto page: Previous 1, 2
Post new topic   Reply to topic View previous topic :: View next topic
 Forum index » Off-Topic Area » Programming
Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group
[ Time: 0.0672s ][ Queries: 13 (0.0053s) ][ GZIP on ]