Go Job Hunting at the LQ Job Marketplace
 Home Forums HCL Reviews Tutorials Articles Register Search Today's Posts Mark Forums Read
 LinuxQuestions.org Nice script to convert numbers between bases (bin/dec/oct/hex)
 Linux - General This Linux forum is for general Linux questions and discussion. If it is Linux Related and doesn't seem to fit in any other forum then this is the place.

Notices

 02-15-2009, 04:38 PM #1 hgate73 LQ Newbie   Registered: Sep 2008 Posts: 17 Rep: Nice script to convert numbers between bases (bin/dec/oct/hex) I had to write this script for an assignment, and it took me hours of pulling out my hair to figure it out (I'm new to shell scripting), so I thought I'd post it. I know it's probably not the most efficient way to do it, since a CASE would probably be better, but it works for me. Basically it converts numbers of one base (I.E. hex numbers like 2F) to another base (I.E. binary or decimal or octal). Let me know if you like it, or if there's a way to improve it. Code: ```#!/bin/bash # Title: bConvert.sh # Purpose: Converts numbers from one base to another # Requiremetns: BASH shell # Author: hgate73 (linuxquestions.org) # Structure: # \$1 is base of number being converted (-d, -h, -b, -o) # \$2 is number to convert # \$3 is base of number to convert to (-d, -h, -b, -o) # Example: ./bConvert.sh -d 3 -b will convert the decimal (-d for DECIMAL) number 3 to binary (-b for BINARY). It should result in 11 # This is to make sure the input value is in upper-case if it is a letter number=\$( echo "\$2" | tr -s '[:lower:]' '[:upper:]' ) # Error checking if [ \$# = 0 ]; then echo "You didn't specify any arguments."; exit; fi ################## # 1. Set IN type # ################## if [ "\$1" = "-b" ]; then #bin/2 inType='2' elif [ "\$1" = "-o" ]; then #oct/8 inType=8 elif [ "\$1" = "-d" ]; then #dec/10 inType=10 elif [ "\$1" = "-h" ]; then #hex/16 inType=16 fi ################### # 2. Set OUT type # ################### if [ "\$3" = "-b" ]; then #bin/2 outType='2' elif [ "\$3" = "-o" ]; then #oct/8 outType=8 elif [ "\$3" = "-d" ]; then #dec/10 outType='10' elif [ "\$3" = "-h" ]; then #hex/16 outType=16 fi ######################### # 3. Perform conversion # ######################### result=\$(echo "obase=\$outType;ibase=\$inType;\$number" | bc); echo \$result``` Last edited by hgate73; 02-15-2009 at 04:40 PM.
 02-15-2009, 05:43 PM #2 i92guboj Gentoo support team   Registered: May 2008 Location: Lucena, Córdoba (Spain) Distribution: Gentoo Posts: 4,051 Rep: This is the way I'd do it: Code: ```#!/bin/bash function die () { echo "\$1" exit 1 # it's better to exit with an error code other than zero, # this way, external programs can know whether this succeeded # or not :) } function convert() { number=\$( echo "\$3" | tr -s '[:lower:]' '[:upper:]' ) result=\$(echo "obase=\$2;ibase=\$1;\$number" | bc) if [ ! "\$?" == "0" ]; then die "bc error: wrong values." fi echo "Original number in base \$1: \$number" echo "Converted number in base \$2: \$result" } # Error checking if [ \$# = 0 ]; then die "You didn't specify any arguments."; fi # Defaults inType=10 outType=16 while [ -n "\$1" ]; do case "\$1" in -i|--input-base) if [ -n "\$2" ]; then inType="\$2" else die " \$1 requires an aditional parameter." fi shift; shift; ;; -o|--output-base) if [ -n "\$2" ]; then outType="\$2" else die " \$1 requires an aditional parameter." fi shift; shift; ;; *) convert \$inType \$outType \$1 shift; ;; esac done``` Case along with shift let you handle the arguments in a smarter and more flexible way (you can use -i and -o on any order, as long as the following argument is the base). Note that it will also convert as many numbers as desired on a single run: Code: ```bconvert -o 3 108762345243 42352453 524352453 Original number in base 10: 108762345243 Converted number in base 3: 101101201211112121020000 Original number in base 10: 42352453 Converted number in base 3: 2221200201122101 Original number in base 10: 524352453 Converted number in base 3: 1100112122212100020``` It's better to use different argument names for different arguments. Your original design is prone to confusion in that regard because the arguments to determine inType and outType are named the same. This script should handle any base, and not just 8, 10 and 16. It also has defaults for inType and outType so you don't forcingly have to specify none. What could be enhanced? Well, the error handling could be better. Also you could add a -h|--help clause in the case statement. The help text could be designed as a function (you already have two examples in that code), a function that should be called either when you use -h or --help or when you invoke the program without arguments. Designing it as a function let's you call it from many places without having to duplicate the code. You could as well add -idec, -ihex, -ibin, -ioct, -ooct, -odec, -ohex, -obin parameters that would be shorthands for these common bases. This is a quick adaptation so it might have some flaws that I haven't yet considered. EDIT: fixed. Last edited by i92guboj; 02-15-2009 at 06:02 PM.
 02-16-2009, 03:38 PM #3 hgate73 LQ Newbie   Registered: Sep 2008 Posts: 17 Original Poster Rep: This is good information, thanks a lot. I knew there had to be a way to do it with CASE statements, but I haven't covered them yet and I don't know how to use them. Thanks for the great example.
 02-17-2009, 03:19 AM #4 H_TeXMeX_H Guru   Registered: Oct 2005 Location: \$RANDOM Distribution: slackware64 Posts: 12,928 Blog Entries: 2 Rep: Sorry, but I'd do this in C not bash.
 02-17-2009, 03:51 AM #5 nx5000 Senior Member   Registered: Sep 2005 Location: Out Posts: 3,307 Rep: Another way Code: ```#!/usr/bin/perl #This program is freeware, after 15 days, you have to purchase it ;-) print unpack("\$ARGV[2]*",pack("\$ARGV[0]*",\$ARGV[1])) . "\n"``` ./script C 3 B 00000011 ./script B 00001111 H 0f floats to native ieee representation: ./script f 1.1 H cdcc8c3f

 Tags base, binary, converter