Showing posts with label function. Show all posts
Showing posts with label function. Show all posts

Wednesday, February 25, 2009

Back To Basics: Getting File Information Using Perl's Stat Function

Hey there,

Today we're going take a (somewhat) beginner's look at extracting lots of useful information from files on Linux or Unix using Perl. More specifically, we'll be using Perl's stat() function. If you're a regular reader, you've probably noticed that we've strayed quite a bit from our original motto (which is screaming in the meta-description tag of every page ;) which is to keep up a blog that appeals to Linux and Unix users and/or admins of any skill level. Lately, we kind of feel like we've neglected the folks newer to the Linux/Unix world. Perhaps we're wrong. We're obviously confused. Perhaps, the next time we start a blog we'll be bit more specific about the subject matter. That being said, we've made our beds and have resigned to lie in them, since the floor is getting uncomfortable again ;)

Today we're going to take a brief introductory look at Perl's stat() function and how you can use it to extract lots of useful information from files, directories, etc (actually, everything in Linux/Unix is a "file" of a certain type). It's incredibly easy to use and, even if you've never used Perl before, very easy to implement. If you're still stuck at the Shebang line in point of reference to Perl/shell scripting, check out that post, as we hope it provides a good base for one of the things you're most likely to find in a Perl or shell script. It also goes beyond just scripting and attacks some other basic concepts.

Here's a very simple Perl script (which, as demonstrated, can be written on the command line as well) that will let you know the user id and group id associated with a particular file. We won't be exploring stat() completely in this post. just enough to get you started and comfortable (you could get the same information by running "ls -l" instead of just "ls," but that would defeat the purpose, right? ;):

host # ls
file.txt
host # perl -e '$file="file.txt";($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks)=stat($file);print "$file : User: $uid - Group: $gid\n"';
file.txt : User: 1000 - Group: 513


Your output may vary depending on what flavour of Linux or Unix you're using. In script format, this command line would look this way (not really all the much different, but, perhaps, easier to read):

#!/usr/bin/perl

$file="file.txt";
($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks)=stat($file);
print "$file : User: $uid - Group: $gid\n"';


When you run this (after giving it execute permission for the user - you :) - ) you get the same result (assuming you called it file.pl):

host# ./file.pl
file.txt : User: 1000 - Group: 513


Granted, today's examples were rudimentary for anyone who's had experience with Perl's functionality and the Unix/Linux shell, but, in this on and off series, we're going to take it a bit slow (we'll probably build on this post every two or three other posts). This is in no way an attempt to dumb-down the blog, just to get back to basics. Think of it as a bracing slap in the face we're giving ourselves to remind us that this blog isn't all about higher concepts.

All of us here, at one point, didn't know what Linux or Unix was, much less how to make any use of it. This interweaving series is for those of you who are just getting started (just like everyone in the business did at some point :)

We look forward to getting more into it. Perhaps the learning curve will be surprisingly fast. At the rate our children are picking up on computers, perhaps the transfer of knowledge won't be quite as difficult as it was in our day. Who can say? We don't know, but we're positive that, as soon as they can, they will ;)

In our next post in this series, we'll look at the components of the Perl stat() function and the rest of the information you can gather from it. Hopefully this post has been easily digestible enough to act as an introduction. If not, please contact us (via the link at the right hand top of every page) and let us know. We write a lot for ourselves (especially Mike, who thinks everything that makes him laugh is funny to everyone else in the entire universe ;), but are committed to providing useful information for you :)

Cheers,

, Mike




Discover the Free Ebook that shows you how to make 100% commissions on ClickBank!



Please note that this blog accepts comments via email only. See our Mission And Policy Statement for further details.

Saturday, May 24, 2008

Simple Perl Script To Demonstrate DNS Lookups In Linux

Hey There,

This weekend post is somewhat of a look-back at a previous post on we did on simple IP and hostname resolution with Perl.

The script we're putting out today is only about half as good as some of the standard hostname/IP checkers out there, and it was specifically written only to accept hostnames and not IP's. If there's a request for it, we could write out the other half, but it's probably best to check out our Perl IP/hostname resolution post and do it for yourself. It's pretty much already written, you just have to reverse the logic (or invert it) somewhat ;)

This Perl script should run on any flavour of Linux, Unix and probably even Windows , assuming you have some sort of Cygwin or MKS *nix-on-Windows setup - or want to go through and manually edit the script to switch the backslashes to forward slashes, etc, so you can use ActivePerl for Windows - Note that, of these three options, only MKS isn't freeware, so if you're working on the cheap, stick with Cygwin or ActivePerl. No offense meant to MKS; it's a fine product but starts out at around 4 or 500 dollars to buy a single developer license.

The script only takes one argument of a hostname, like so:

host # ./double.pl www.google.com

The script is basically meant to reinforce Perl's basic network lookup functions that we went over a post or so ago, and provide a relatively lame means of double-checking a lookup to determine if it's bogus.

The skeleton of the script (logically) is this:

1. Lookup the IP of the hostname supplied.
2. Lookup the hostname using the IP we got in step 1.
3. Determine if the hostname's gotten in steps 1 and 2 match.
4. If they do, then we quit; assuming everything's okay.
5. If they don't match, we lookup the IP of the second hostname we received.
6. Lookup the IP of the second hostname (that we got in step 2)
7. Determine if the IP's (gotten in steps 1 and 6) match.
8. If they do, then we quit; assuming all is well.
9. If they don't, we still quit; we just complain about it ;)

This script should also aid in examining the opposite of a double-reverse-lookup (The double-reverse-lookup being IP to Name to IP mapping, with this being Name to IP to Name mapping). Some sites use Double Reverse Lookups as a security measure, but whether or not the process protects anything at all, or is just a waste of resources, is debatable. Just do a search for it online and you'll be inundated with polemic for as long as you can stand to read.

For our purposes, this is just another way to learn more about how things work with Perl's networking functions and how you can better work with them :)

This is what you can expect to see from this script (approximately):

host # ./double.pl www.google.com

Hostname: www.google.com = IP: 64.233.167.99

IP: 64.233.167.99 = Hostname: py-in-f99.google.com

www.google.com and py-in-f99.google.com Do Not Match
Checking Reverse...

64.233.167.99 and 64.233.167.99 match
Everything is probably ok!


Here's hoping this helps you out, and best of luck if you decide to write the opposite (which would be the "real" Double Reverse Lookup :)

Cheers,


Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

#!/usr/bin/perl

#
# double.pl - Double Check That Hostnames Match The IP's They're Advertising
#
# 2008 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#

use Socket;

if ( $#ARGV != 0 ) {
print "Usage: $0 hostname\n";
exit(1);
}

$entry = $ARGV[0];

$hostname1 = $entry;
$ip1 = gethostbyname($hostname1) || die "error - gethostbyname: $!\n\n";
$hostip1 = inet_ntoa($ip1) || die "error - inet_ntoa: $!\n\n";
print "\nHostname: $hostname1 = IP: $hostip1\n\n";
$hostname2 = gethostbyaddr(inet_aton($hostip1),AF_INET) || die "error - inet_aton: $!\n\n";
print "IP: $hostip1 = Hostname: $hostname2\n\n";
if ( $hostname1 eq $hostname2 ) {
print "$hostname1 and $hostname2 Match!\n";
print "Good Deal!\n\n";
exit(0);
} else {
print "$hostname1 and $hostname2 Do Not Match\n";
print "Checking Reverse...\n\n";
$ip2 = gethostbyname($hostname2) || die "error - gethostbyname: $!\n\n";
$hostip2 = inet_ntoa($ip2) || die "error - inet_ntoa: $!\n\n";
if ( $hostip1 eq $hostip2 ) {
print "$hostip1 and $hostip2 match\n";
print "Everything is probably ok!\n\n";
exit(0);
} else {
print "$hostip1 and $hostip2 don't match\n";
print "This DNS may be bogus or setup incorrectly!\n\n";
exit(0);
}
}


, Mike

Sunday, May 4, 2008

Reversing All Lines In A File On Linux Or Unix Using Perl

Good evening-day-morning-afternoon :)

In response to some positive feedback, and some additional questions, prompted by our earlier post on using Perl to mirror lines in a file on Linux or Unix, today we're dispensing with yet another Perl script to do almost the same thing, but with an extra twist. While our original mirror file script reversed each line, this one will attempt to do the same thing while also reversing the order of the lines. If you have a nervous condition you should probably quit reading this is, as it is only going to get more intense ;)

The good news is that I already know it works. The bad news is available at your local newsstand or in that meeting you should really try to blow off ;) Sorry... but only because the bad jokes are intentional.

So, when we're done crunching a file with today's script it will come out with all the lines reading from left to right and with the first line being the last, the second line being the second to last, and so on until the last line, which will be the first. End of story... or is it? ;)

Again, we're going to take a quick look at another useful function in this script. Since the rest of them are the same as in the script that prompted this one (split, join, undef and push), I should refer you to that post on mirroring file lines so that we don't waste too much space with duplicate content. It's interesting to look at the two side-by-side to really see the difference.

In today's post we'll check out the use of this one function (Note that, this time, we'll assume that the array @array consists of no members at all:

unshift - This function does the same thing as the "push" function we used in our last post, except that it will "unshift" a variable on to the "right side" of an array. The name isn't as intuitive as "push," but, if it helps, when you "shift" a variable from an array, you're pulling it out of the "left side." So, naturally, "unshifting" is adding to the "right side." ...No matter how I explain it, it will never make sense. It's just one of those words you have to accept on faith. Like "defenestration." <--- Apologies for the cheap-shot at Microsoft. That word is officially defined as "the act of throwing someone or something out of a window." It's only a few small steps to the jab I was going for ;)

Ex:
unshift(@array, "a");
<--- @array now equals "a"
unshift(@array, "b"); <--- @array now equals "a" "b"
unshift(@array, "c"); <--- @array now equals "a" "b" "c"

Again, enjoy, and I hope this helps you out with whatever you're doing that it might help you out with ;)

Cheers,

SAMPLE RUN:

host # cat words|head -3;cat words|tail -3
<--- The beginning and end of the file we're going to "reverse"
Aarhus
Aaron
Ababa
Zulu
Zulus
Zurich
host # ./mirror.pl words
host # ls
. .. reverse.pl words words.reverse
<--- Our newly created file is called "words.reverse"
host # cat words.reverse|head -3;cat words.reverse|tail -3 <--- And, once again (since I tested this a few times already), the reversal of the file seems to have worked!
hciruZ
suluZ
uluZ
ababA
noraA
suhraA

host # wc -l words* <--- Just double checking here to make sure that the number of characters in our original file and the reverse file are exactly the same, which they should be.
45378 words
45378 words.reverse
90756 total



Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

#!/usr/bin/perl

# reverse.pl - reverse each line, and its position in a file
#
# 2008 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#

if ( $#ARGV != 0 ) {
print "Usage: $0 text_file\n";
exit(1);
}

$text_file=$ARGV[0];

open(TXT, "<$text_file");
@txt = <TXT>;
close(TXT);

foreach $ln (@txt) {
chomp($ln);
@ln = split(//, $ln);
$ln_len = @ln;
undef(@rev);
while ( $ln_len > 0 ) {
push(@rev, $ln[${ln_len}-1]);
$ln_len--;
}
$rev = join(/ /, @rev);
unshift(@reverse, "$rev");
}
open(RTXT, ">${text_file}.reverse");
foreach $backward (@reverse) {
print RTXT "$backward\n";
}
close(RTXT);
exit(0);


, Mike

Saturday, May 3, 2008

Perl Script To Mirror Lines In A File On Linux Or Unix

Good afternoon-morning-day-evening :)

In much the same vein as our previously posted script to do weak encryption with Octal Dump, today we're throwing out another Perl script to do something possibly equally worthless, but still somewhat entertaining ;) Since it's written in Perl, and uses that language's specific constructs (i.e. No "system" calls), it should run equally well on Linux or Unix. The logic in the script is simple enough that it should probably work going back a few major versions.

As much as this may not seem to be of any use to you now, knowing how to mirror (or reverse, since many people, including myself, don't have any mirror-friendly fonts ;) each line in a file can be beneficial. Although no one in the office is likely to come up to you and say "Mr. sysadmin, sir (of course, I'm exaggerating. People are much more formal than that normally ;), Can you print every single line of this report reading from right-to-left instead of the standard left-to-right?", it's even more unlikely that, if this were to happen, any business/war jargon would be used. I can't imagine something like this ever being "mission critical" or required for any sort of "code red" situation. If it ever is, you'll be really glad you know how to do this...

But, at a fundamental level, it's good to understand the basic functionality of Perl and how to deal with scalar variables (or string variables), arrays and how to muck around with them (or make them work for you ;) In this particular script, the building blocks of some very useful functions of Perl are employed (to a dubious end, I'll admit) and, hopefully, presented in an easy to understand fashion. Over time, we'll dig into every little thing there is to know (If that can be cranked out in one life time ;) with regards to each function. In the mean time, check out the use of these four functions (Note that, for all, we'll assume that the variable $variable is defined as "abcd" and the array @array consists of four members: a, b, c and d:

split - This function will take a scalar variable and "split" it, on a delimiter, into an array:

Ex: @array = split(//, $variable); <--- Now @array has four members (a, b, c and d) that it got from $variable

join - This function will take an array and "join" it into one scalar variable:

Ex: $variable = join(/ /, @array); <--- Now $variable equals "abcd" since it contains all 4 members of @array joined together by an empty delimiter "/ /" (that is, each character, or space, is considered a separate member of the array)

undef - This function will "undefine" our array, in this case. It can be used on scalar, array and hash variables as well.

Ex: undef(@array); <--- Now @array is not just empty, it isn't even defined. It may as well not exist.

push - This function will "push" a variable (scalar, array, hash, or references to same, and more -- getting way off-topic ;) onto the left side of an array. Subsequent pushes of extra variables are added from the left, so if you push three variables into an array (a, b and c, for instance) in one order, they'll actually end up in the array in the opposite order.

Ex:
push(@array, "a");
<--- @array now equals "a"
push(@array, "b"); <--- @array now equals "b" "a"
push(@array, "c"); <--- @array now equals "c" "b" "a"

In any event, enjoy, and I hope this helps you out if you're beginning to learn the Perl scripting language!

Best wishes,

SAMPLE RUN:

host # cat words|head -3;cat words|tail -3
<--- The beginning and end of the file we're going to "mirror"
Aarhus
Aaron
Ababa
Zulu
Zulus
Zurich
host # ./mirror.pl words
host # ls
. .. mirror.pl words words.mirror
<--- Our newly created file is called "words.mirror"
host # cat words.mirror|head -3;cat words.mirror|tail -3 <--- And (good deal), the mirroring seems to have worked!
suhraA
noraA
ababA
uluZ
suluZ
hciruZ
host # wc -l words*
<--- Just double checking here to make sure that the number of characters in our original file and the mirror file are exactly the same, which they should be.
45378 words
45378 words.mirror
90756 total



Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

#!/usr/bin/perl

#
# mirror.pl - print an entire file backward, line by line
#
# 2008 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#

if ( $#ARGV != 0 ) {
print "Usage: $0 text_file\n";
exit(1);
}

$text_file=$ARGV[0];

open(TXT, "<$text_file");
@txt = <TXT>;
close(TXT);

open(RTXT, ">${text_file}.mirror");
foreach $ln (@txt) {
chomp($ln);
@ln = split(//, $ln);
$ln_len = @ln;
undef(@rev);
while ( $ln_len > 0 ) {
push(@rev, $ln[${ln_len}-1]);
$ln_len--;
}
$rev = join(/ /, @rev);
print RTXT "$rev\n";
}
close(RTXT);
exit(0);


, Mike

Sunday, April 27, 2008

Perl Script To Translate Signal Names And Numbers

Hey There,

For this "Lazy Sunday" post I threw together a quick little Perl script to help out further with what we went over more thoroughly in our previous post on signal definitions in Linux and Unix.

This script takes at least one argument (or it throws a fit and refuses to cooperate with you ;) of either a signal name or signal number, which it will then translate to the other (does the way I wrote that make sense? ;)

So, if you want to know what signals 4 and 5 do, you could run:

host # ./siggy.pl 4 5
Signal Number 4 = ILL
Signal Number 5 = TRAP


And see the (somewhat more verbose) translations from the system includes. Conversely, you could want to know what numbers the TERM and KILL signals are, which you could get by running:

host # ./siggy.pl TERM KILL
Signal Name TERM = 15
Signal Name KILL = 9


Or you can mix and match. Do whatever, you want. If you throw the script an argument it doesn't understand it will react accordingly ;)

host # ./siggy.pl hup 8 ... 9
Signal Name HUP = 1
Signal Number 8 = FPE
...: What is that supposed to mean?
Signal Number 9 = KILL


One interesting thing in the script is the use of an absolute subroutine call. Even though I put the "use Sys::SigAction;" line in the script, Perl was interpreting the function calls (like sig_number()) as belonging to the Main:: module. Pretty much every function, or command, in Perl does. "print," for example, is actually Main::print, so I had to use "absolute" naming. Writing "Sys::SigAction::sig_number()" (in this instance) is one way to make sure that Perl knows exactly where to look for that subroutine to run :)

Cheers,


Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

#!/usr/bin/perl

#
# siggy.pl
#
# 2008 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#

if ( $#ARGV < 0 ) {
print "Usage: $0 signalNumber1 [signalNumbern...]\n";
exit(1);
}

use Sys::SigAction;

@signos = @ARGV;

foreach $sig (@signos) {
if ( $sig =~ /[A-Za-z]+/ ) {
$sig = uc($sig);
$signum=Sys::SigAction::sig_number( $sig );
print "Signal Name $sig = $signum\n";
} elsif ($sig =~ /[0-9]+/) {
$signame=Sys::SigAction::sig_name( $sig );
print "Signal Number $sig = $signame\n";
} else {
print "$sig: What is that supposed to mean?\n";
}
}


, Mike

Tuesday, April 22, 2008

Functions Vs. Subroutines In Perl And Bash - Palindromes Revisited

Hey There,

As the clever title of today's post suggests, this is the follow up to our post on scripting out a way to determine if a string is a palindrome using Perl.

One of the main things to note (which isn't the only difference, of course) is the way in which the Bash shell and Perl deal differently with "routines." In our Perl script, we did the meat of our recursive work inside a "subroutine." In today's Bash script, that same work is handled inside a "function."

Functionally speaking, both a Perl "subroutine" (Identified by the "sub" declaration) and a Bash "function" (Identified by the "function" declaration) do the same things. They allow you to create a block of code for use within in your script. Naturally, functions and/or subroutines, are a great help if you find that your script consists of typing the same set of instructions more than once (if you have to type the same block of code more than twice, they're even better ;)

Technically speaking, there are some major differences between the two that should be noted. These should be platform independent and true for both Bash and Perl on Linux or Unix.

In Perl, since all of the information in the script is processed before the script is run, you can include your "subroutine" anywhere in the script, even if it's after the line on which you call it. It's common practice to put subroutines at the bottom of the script, but you can put them anywhere within the script that you like, if you're so inclined.

In Bash, since the script is parsed from top-to-bottom in a left-to-right fashion, "functions" absolutely need to appear in the script before the line on which they are called. If you put a function definition at the bottom of your Bash shell script and call that function 15 lines prior, you'll receive something along the order of a "command not found" error.

In Perl, when you pass arguments to a subroutine, you have a few different ways you can do it (basically, deprecated methods still work), but the most elegant way to pass simple variables to your Perl subroutine is to include them within parentheses, separated by commas, like so:

MySub( $var1, $var2, $var3);

The subroutine that would accept, and process, all of those arguments may look something like this:

sub MySub( $var1, $var2, $var3) {
print "$var1 $var2 $var3\n";
}


In Bash, when you pass arguments to a function, you can just pass them as if they were arguments to a regular command, like this:

MyFunction $var1 $var2 $var3

The function that would accept, and process, these arguments may look something like this:

function MyFunction {
echo "$var1 $var2 $var3"
}


Interesting side note: In Bash, if you declare a function, you can leave out the reserved word "function" if you want to, but this requires that you use parentheses, like with Perl. So you could write your function like this:

MyFunction () {
echo "$var1 $var2 $var3"
}


However, if you opt to use the reserved word "function" when declaring your function (like we do), the parentheses following the function name are optional :)

You may have noted that we haven't mentioned anything about "scope" with regards to variables and functions or subroutines. This is on purpose. We'll inevitably tackle that in a later post, but it's beyond the "scope" of this one (that was a truly painful pun for all of us... but utterly unavoidable ;)

On that note (for the palindromes), in our Bash script we've taken advantage of that "lack of scope" and simply set the "$status" variable globally within the palindrome function. In our Perl script, we used "return" to pass back either a 0 or a 1 to the calling procedure. The major difference here is that our Perl script was returning a code back to a variable which was defining its value based on the outcome of the subroutine process, so:

$status = palindrome( @string, $chars, $count );

was giving the "$status" variable a value of 0 or 1, depending on what the "palindrome" subroutine returned. In Bash, we jumped right over the middle man and just set the global "$status" variable from within the function (This isn't generally recommended, but okay for our purposes here). Assuming there are no bugs in your version of Bash that mangle the scope of variables within functions, the only risk you're taking, by defining a global variable from within a function, is that you'll forget about it and redefine it outside the function, thereby overwriting the value. But, again, that's for another day, as I can feel an essay coming on ;)

Hope you enjoy the Bash version of our simple palindrome script and that it helps you see the correlation between not only functions and subroutines, but some other aspects of coding that are either common, or unique, to both Bash and Perl.

Best wishes,

Cheers,


Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

#!/bin/bash

#
# bashpal.sh
#
# 2008 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#

function palindrome {
if [ "${string:${count}:1}" == "${string:${chars}-${count}-1:1}" ]
then
let count=$count+1;
palindrome "$string" "$chars" "$count"
fi
if [ $count -eq $chars ]
then
status=1;
else
status=0;
fi
}

printf "Enter A String: "
read string

chars=${#string}
count=0
palindrome "$string" "$chars" "$count"

if [ $status -eq 1 ]
then
printf "\n That String Is A Palindrome.\n\n"
else
printf "\n That String Is Not A Palindrome.\n\n"
fi


, Mike




Tuesday, March 18, 2008

Using Unpack To Convert Binary Values To Decimal

Hey There,

Today's post may seem like a step back for regular readers, but I like to keep this blog accessible, so I've decided to revisited the Perl unpack function to demonstrate how it can be used in one of its simplest forms on either Linux or Unix. A more advanced example can be found in our previous post on taking a look inside the wtmpx file.

The Perl script we're presenting today only consists of one simple unpack function surrounded by a whole bunch of processing code. If certain parts were modularized, this would make a decent simple function in a greater calculator/conversion script.

Notice that when we use the unpack value to convert a binary number, say:

11101110

to the decimal number:

238

all we're really doing is feeding the value (11101110) to the unpack function and telling it to convert the input using a standard template ("C" in this case - which stands for an unsigned character - octet - value). You'll not that we've actually put "C*" to account for an infinitely variable number of unsigned octet character values. If we didn't do this (Just put "C" instead), the unpack function would only process the first character the script fed it, so our original input:

11101110

would translate to this:

1

So, as you can see, in this simple function - unpack("C*", $binary) - the definition of the predefined template value C can make a huge amount of difference. It can also allow you to be as specific as you need to be. For instance - unpack("CC", $binary) - would produce:

3

from the same input. This can also be written as - unpack("C2", $binary) - which will save you a lot of typing if you want to match exactly 245 C's ;)

Hope you find this script useful and that it helps you to get more into Perl's pack and unpack functions. Once you get past the seeming incomprehensibility of the general statements, it all makes sense :)

Cheers,


Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

#!/usr/bin/perl

#
# bd - convert binary numbers to decimal
#
# 2008 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#

print "Binary Number:\t";
chomp ($binary=<stdin>);
@bitvalue = unpack("C*", $binary);
$bitvalue = @bitvalue;
$substring = $bitvalue - 1;
while ($substring ne -1) {
$number = substr($binary, $substring, 1);
$binarray[$substring] = $number;
--$substring;
}
@decarray = reverse(@binarray);
$exponent = 0;
foreach $subscript (@decarray) {
if ($subscript == 1) {
$subscript = 2 ** $exponent;
} elsif ($subscript == 0) {
$subscript = 0;
} else {
print "Are you sure you know what a Binary Number is?\nMaybe you shouldn't be using this...\n";
exit;
}
$exponent++;
}
$decimal = "0";
foreach $integer (@decarray) {
$decimal += $integer;
}
print "Decimal Value:\t$decimal\n";
exit;


, Mike