IP

Showing posts with label Perl. Show all posts
Showing posts with label Perl. Show all posts

Thursday, August 4, 2011

[PERL] Md5 Brute Force Script


PHP Code:
#!/usr/bin/perl

# * md5crack.pl
# *Usage:
# *./md5crack <charset> <mincount> <maxcount> <yourMD5>
# *nUm/b0

$ver "01"$dbgtmr "1"#Intervall of showing the current speed + lastpassword in seconds.
if ($dbgtmr<=0){ die "Set dbgtmr to a value >=1 !\n";};
use 
Digest::MD5 qw(md5_hex);
use 
Time::HiRes qw(gettimeofday);

if (
$ARGV[0]=~"a") { $alpha "abcdefghijklmnopqrstuvwxyz";}
if (
$ARGV[0]=~"A") { $alpha $alpha"ABCDEFGHIJKLMNOPQRSTUVWXYZ";}
if (
$ARGV[0]=~"d") { $alpha $alpha."1234567890";}
if (
$ARGV[0]=~"x") { $alpha $alpha"!\"\$%&/()=?-.:\\*'-_:.;,";}

if (
$alpha eq "" or $ARGV[3eq "") {usage();};
if (
length($ARGV[3]) != 32) { die "Sorry but it seems that the MD5 is not valid!\n";};

print 
"Selected charset for attack: '$alpha\'\n";
print 
"Going to Crack '$ARGV[3]'...\n";

for (
my $t=$ARGV[1];$t<=$ARGV[2];$t++){ crack ($t);
}
sub usage{
print 
"\n\nMD5 Hash Bruteforce Kit v_$ver\n";
print 
"by unix_chro alias backtrack (311733@yahoo.com)\n";
print 
"Member in staff leader:elite-members,ubuntu-hackers\n\n";
print 
"USAGE\n";
print 
"./md5crack <charset> <mincount> <maxcount> <yourMD5>\n";
print 
" Charset can be: [aAdx]\n";
print 
" a = {'a','b','c',...}\n";
print 
" A = {'A','B','C',...}\n";
print 
" d = {'1','2','3',...}\n";
print 
" x = {'!','\"',' ',...}\n";
print 
"EXAMPLE FOR CRACKING A MD5 HASH\n";
print 
"./md5crack.pl ad 1 3 900150983cd24fb0d6963f7d28e17f72\n";
print 
" This example tries to crack the given MD5 with all lowercase Alphas and all digits.\n";
print 
" MD5 Kit only tries combinations with a length from 1 and 3 characters.\n-------\n";
print 
"./md5crack.pl aA 3 3 900150983cd24fb0d6963f7d28e17f72\n";
print 
" This example tries to crack the given MD5 with all lowercase Alphas and all uppercase Alphas.\n";
print 
" MD5 Kit only tries passwords which length is exactly 3 characters.\n-------\n";
print 
"./md5crack.pl aAdx 1 10 900150983cd24fb0d6963f7d28e17f72\n";
print 
" This example tries to crack the given MD5 with nearly every character.\n";
print 
" MD5 Kit only tries combinations with a length from 1 to 10 characters.\n";
die 
"Quitting...\n";
}
sub crack$CharSet shift;
@
RawString = ();
for (
my $i =0;$i<$CharSet;$i++){ $RawString[i] = 0;} $Start gettimeofday();
do{
for (
my $i =0;$i<$CharSet;$i++){
if (
$RawString[$i] > length($alpha)-1){
if (
$i==$CharSet-1){
print 
"Bruteforcing done with $CharSet Chars. No Results.\n"$cnt=0;
return 
false;
$RawString[$i+1]++; $RawString[$i]=0;
}
################################################## # $ret "";
for (
my $i =0;$i<$CharSet;$i++){ $ret $ret substr($alpha,$RawString[$i],1);} $hash md5_hex($ret); $cnt++; $Stop gettimeofday();
if (
$Stop-$Start>$dbgtmr){ $cnt int($cnt/$dbgtmr);
print 
"$cnt hashes\\second.\tLast Pass '$ret\'\n"$cnt=0$Start gettimeofday();
}
print 
"$ARGV[3] != $hash ($ret)\n";
if (
$ARGV[3eq $hash){
die 
"\n**** Password Cracked! => $ret\n";
################################################## #
#checkhash($CharSet)."\n";
$RawString[0]++;
}while(
$RawString[$CharSet-1]<length($alpha));
}
sub checkhash$CharSet shift$ret "";
for (
my $i =0;$i<$CharSet;$i++){ $ret $ret substr($alpha,$RawString[$i],1);} $hash md5_hex($ret); $cnt++; $Stop gettimeofday();
if (
$Stop-$Start>$dbgtmr){ $cnt int($cnt/$dbgtmr);
print 
"$cnt hashes\\second.\tLast Pass '$ret\'\n"$cnt=0$Start gettimeofday();
}

if (
$ARGV[3eq $hash){
die 
"\n**** Password Cracked! => $ret\n";
}

}  

Very fast and works nicely. * Thought i'd share, could be useful to anyone learninG perl. Enj0y ! *\m/ 


tx2 #Xdem0






~./Supp0rT#:
http://www.activestate.com/activeperl/
http://www.perl.com/download.csp

Sunday, December 19, 2010

Learn Perl in 10 lessons Lesson 6



Page 6 of 1 In the previous lessons we've used a lot of functions that were built-in the language. For instance, we used "split", "print", "chomp" ...etc. What we haven't done yet, is to define our own functions. In Perl we call them subroutines. 
Subroutines

A subroutine is basically a few lines of code you give a name to. You can then run these lines by simply calling the subroutine from your script. You can pass arguments from the scripts to the subroutine, and depending on the subroutine it can return a result or not.
If you've never used any programming language before, you probably don't know what to think right now. But don't worry, it's very simple. Let's look at an example to make things a little bit clearer. 
Have a look at the following script: 




Code:
#!/usr/bin/perlprint "Here are the lines containing house:\n";open (FILE, "/etc/myProgram/myFile");while ($line = <FILE>) { if ($line =~ /house/) { print $line; }}print "And here are the lines containing dog:\n";open (FILE, "/etc/myProgram/myFile");while ($line = <FILE>) { if ($line =~ /dog/) { print $line; }}
As you probably guessed, this script does something pretty stupid. It shows you the lines which contain "house" and then the lines which contain "dog" within the file /etc/myProgram/myFile. It's not what it does that is shocking though, it's how it does it.
Look at the code. It does exactly the same thing twice... once for "house" and once for "dog". If there was a bug in the way it shows the lines containing "house", would I remember to also fix the same bug for "dog" when I fix it? Of course not, I'm only human after all.
The idea is simple. Instead of showing the lines which contain "dog" or "house", we'll define a subroutine which can show lines containing "something". And then we'll call this subroutine with "dog" and "house".



Code:
#!/usr/bin/perlsub showLines{ my ($keyword) = @_; print "Here are the lines containing $keyword:\n"; open (FILE, "/etc/myProgram/myFile"); while ($line = <FILE>) { if ($line =~ /$keyword/) { print $line; } }}showLines("house");showLines("dog");
As you can see, we reduced the amount of code and more importantly, we removed code that was repeated twice. The first part of the script defines a subroutine called showLines. The second part simply calls it twice, once giving it the argument "house", and then giving it the argument "dog". 
Within the subroutine, we simply replaced the references to "dog" and "house" with a variable representing the argument. When you call a subroutine with an argument or a list of arguments, the subroutine is executed and the arguments are stored in the following array variable: @_. 
The line my ($keyword) = @_; is simply assigning the values of the arguments to an array containing variables. In this case the value of the argument is assigned to $keyword, which receives "house" and then "dog" when called from the script. 
Local variables

The reason why the assignment is preceded by "my" is because we want the $keyword variable to be local to the subroutine. When a variable is defined with the keyword "my" it becomes a local variable and it only exists within the subroutine. This way, we do not have to worry whether or not another variable with the same name is defined in the script. It's always a good idea to make variables local inside your subroutine, so always declare them with the "my" keyword.
arguments

Let's go further. Instead of a subroutine which prints the lines containing "something" from the file /etc/myProgram/myFile, we'll define a subroutine which prints the lines containing "something" from "some" file. This time we'll use two arguments: the file to look into and the keyword to search for. 




Code:
#!/usr/bin/perlsub showLines{ my ($keyword, $file) = @_; print "Here are the lines containing $keyword within $file:\n"; open (FILE, "$file"); while ($line = <FILE>) { if ($line =~ /$keyword/) { print $line; } }}showLines("house", "/etc/myProgram/myFile");showLines("dog", "/etc/myProgram/myFile");
We could even define a subroutine which searches for a keyword in a list of files. For this we would pass two arguments: a keyword, and an array containing filenames.




Code:
#!/usr/bin/perlsub showLines{ my $keyword = shift (@_); my @files = @_; print "Here are the lines containing $keyword $files:\n"; foreach $file (@files) { print "...in file $file:\n"; open (FILE, "$file"); while ($line = <FILE>) { if ($line =~ /$keyword/) { print $line; } } }}@files = ("/etc/myProgram/myFile", "/etc/myProgram/myOtherFile");showLines("house", @files);showLines("dog", @files);
In this example, note how the subroutine retrieves the arguments. The array @_ initially contains two objects, a scalar and an array. By using the "shift" Perl function we retrieved and deleted the first element of the array and assigned it to the local variable $keyword. We're then left with @_ only containing the array of filenames. 
Returning something

Subroutines can return values. In our previous example, our subroutine was returning nothing. We were simply calling it and it was outputting some lines on the screen. In this example, we'd like the subroutine to do the same, but also to count the number of lines it found and to return it. 


Code:
#!/usr/bin/perlsub showLines{ my $keyword = shift (@_); my @files = @_; print "Here are the lines containing $keyword $files:\n"; my $numberOfLines = 0; foreach $file (@files) { print "...in file $file:\n"; open (FILE, "$file"); while ($line = <FILE>) { if ($line =~ /$keyword/) { print $line; $numberOfLines++; } } } return ($numberOfLines);}@files = ("/etc/myProgram/myFile", "/etc/myProgram/myOtherFile");$nb = showLines("house", @files);print "$nb lines found\n";$nb = showLines("dog", @files);print "$nb lines found\n";
As you can see, the subroutine simply returns the number of lines by using the "return" keyword. In the script, the return value is assigned to the variable $nb. 
Conclusion

Thanks to subroutines you can now define code which can be called more than once. Through the use of arguments and return values, you can make your subroutines more flexible. By extracting common behavior and defining it within subroutines you'll reduce the cost of maintenance in your scripts and the number of eventual bugs it might contain. In most cases this will also make your scripts more scalable. In the next lesson we'll look at how to define our subroutines outside of our script, so that they can be called and used by more than one script. 

Learn Perl in 10 lessons Lesson 5





Executing system commands

Perl provides a function called �system� which canexecute a command or a set of commands directly on the operatingsystem. In fact, Perl passes the command to the operating system, whichexecutes it, and then returns the result back to Perl.

So, for instance, the following Perl script prints the content of the current directory:

#!/usr/bin/perl

system("ls");

What actually happens is that the Unix process which runs the Perlinterpreter forks and the newly created child Unix process executes the�ls� command. When the execution finishes, it returns theexit code of the command back to the Perl interpreter.

If you are familiar with Unix commands exit codes you can test thesuccess of the execution of your command by assigning the return valueof �system� to a variable, and then evaluate this variable.For instance:

$lsExecutedSuccessfully = system(�ls�);

Here, if �ls� executes successfully, the variable$lsExecutedSuccessfully receives the value 0. This value corresponds tothe successful exit code of the command �ls�.
Executing system commands and capturing the output

Sometimes, when you run a Linux command from your Perl script you'remore interested in what it writes on the screen than in its exit code.For instance, when you execute �ls� you're more likely tobe interested in the list of files being printed on the screen than inthe value 0 returned by �system�.

To achieve this, you can use evaluated quotes �`�instead of �system�. Not only does it executes the command,but it also returns what the commands writes in its standard output:

@files = `ls`;

In this example, the listing of the files returned by�ls� does not appear on the screen. Instead, it gets storedin the @files array.
Changing the working directory

In the shell you would type "cd /home" to change the workingdirectory to /home. You could write the following in your Perl script:

system("cd /home");

But it would have no effect. In fact, since the system call forksfrom the process used by the interpreter, it doesn't change the workingdirectory of your script. Instead, you can use a Perl function called"chdir":

chdir "/home";
Interacting with the filesystem

Perl provides a lot of functions to interact with the files anddirectories of your filesystem. Here are some of these handy functions:
chmod

"chmod" changes the permissions of a file or a list of files andreturns the number of files that were changed. The first argument mustbe the numerical mode. Examples:

chmod 0777, "/home/clem/program.pl";

chmod 0777, @myFiles;
symlink

"symlink" creates a symbolic link. It is the equivalent of "ln -s".The first argument is the file name, the second argument is the linkname. Example:

symlink "/home/clem/program.pl", "/usr/bin/program";
mkdir

"mkdir" creates a directory. The first argument is the name of thedirectory and the second argument is the octal mode which defines thepermissions for that directory. For example:

mkdir "/home/clem/perl_programs", 0664;
rename

"rename" is the equivalent of "mv" in Unix. It renames or moves a file. Example:

rename "/home/clem/program.pl", "/home/clem/program";
rmdir

"rmdir" deletes a directory, but only if it is empty. Example:

rmdir "/home/clem/perl_programs";
stat

"stat" returns a 13-element array which represent the properties of a file. The elements of the array are :

0: $dev, 1: $ino, 2: $mode, 3: $nlink, 4: $uid, 5: $gid, 6: $rdev,7: $size, 8: $atime, 9: $mtime, 10: $ctime, 11: $blksize, 12: $blocks

Example:

stat "/home/clem/program.pl";
unlink

"unlink" deletes a file or a list of files. Example:

unlink "/home/clem/program.pl";
Perl Script Exercise: Netswitch

In this exercise, we want to be able to switch between networks. Wedefined network configuration files in a directory called "networks".

For instance, here is the content of ./networks/home:

interface=eth2

type=dhcp

proxy=none

And here is the content of ./networks/work:

interface=eth1

type=dhcp

proxy=www-proxy.work.com

proxy_port=8080

The following Perl script takes a network name as its command lineargument, opens the file with the same name from ./networks and setsthe network interface with the data taken from the content of that file:

#!/usr/bin/perl

#default values

$interface="none";

$type="none";

$address="none";

$gateway="none";

$dns="none";

$proxy="none";

$proxy_port = "none";

#gather information from the network file

$network = $1;

$networkFile = "./networks/$network";

open (NETWORK, "$networkFile") or die "$networkFile not found or not readable\n";

while ($line = ) {

chomp $line;

($variable, $value) = split /=/, $line;

if ($variable eq "interface") $interface = $value;

elsif ($variable eq "type") $type = $value;

elsif ($variable eq "address") $address = $value;

elsif ($variable eq "gateway") $gateway = $value;

elsif ($variable eq "dns") $dns = $value;

elsif ($variable eq "proxy") $proxy = $value;

elsif ($variable eq "proxy_port") $proxy_port = $value;

}

#make sure the type and interface are defined

if ($interface eq "none") die "Interface name not defined\n";

if ($type eq "none") die "Network type (dhcp, static) not define\n";

if ($type eq "dhcp") {

print "Network type: dhcp\n";

#just get an IP address and settings from the DHCP Server

system("dhclient");

}

elsif ($type eq "static") {

print "Network type: static\n";

#bring the interface up

if ($address eq "none") die ("IP address not defined\n");

system("ifconfig $interface $address up");

if ($gateway ne "none") {

print "Gateway: $gateway\n";

system("route add default gw $gateway");

}

if ($dns ne "none") {

print "DNS Server: $dns\n";

$strNameServer = "cat "."'"."nameserver $dns"."' > /etc/resolv.conf";

system($strNameServer);

}

}

else die "Bad network type : $type. Use dhcp or static.\n";

Try to understand each line of that script. The script doesn't setthe proxy in APT, Firefox...etc. See if you can update the script toadd such functionality. Also, it would be great if the script couldlist the possible networks available when the user types "netswitch-l". As there are many ways to solve a problem, especially in Perl,please post your solutions and ideas. Together you should be able towrite a great network switcher.

You now know all you need to start writing this script, however if you have any questions do not hesitate to ask.

Learn Perl in 10 lessons Lesson 4




String comparisons
The =~ operator

Perl provides an operator which you'll find very useful to parseand search files: "=~". If you are not familiar with thisoperator, think of it as a "contains" operator. Forinstance:

"helloworld" =~ "world" returns true, as "helloworld" contains "world".
"helloworld" =~ "o worl" also returns true since "oworl" is included in the string "hello world".
"helloworld" =~ "wrld" returns false because thestring "hello world" does not contain "wrld".

Using the =~ operator you can easily testif a variable contains a particular string, and this will help you alot while parsing text files. You can also use regular expressions inconjonction with the =~ operator. Although it is too early at thisstage to study regular expressions in details, here are sometechniques that you can use with =~.

We replace the doublequotes by forward slashes in order to tell our =~ operator that we'renot simply looking for a string anymore but for a matching pattern(with a bit of logic inside it):

"helloworld" =~ "world" is the same as "helloworld" =~ /world/

Although"world" represents a string and /world/ represents anexpression, these two instructions return true. By adding logic tothe expression, we can refine the meaning of our =~ operator.
=~/^Starts with/

A leading ^ sign changes the meaning of the operator from"contains" to "starts with":

"helloworld" =~ /world/ returns true because "hello world"contains "world".
"helloworld" =~ /^world/ returns false since "hello world"doesn't start with "world".
"helloworld" =~ /^hell/returns true because "hello world" starts with"hell".
=~ /Ends with$/

By adding a $ sign in the end of the expression you can change themeaning of the operator from "contains" to "endswith":

"hello world"=~ /world/ returns true because "hello world"contains "world".
"helloworld" =~ /world$/ also returns true, but this time it'sbecause "hello world" ends with "world".
"helloworld" =~ /hello$/ returns false, because "helloworld" doesn't end with "hello".
The eq and ne operators

You can use both the ^ and $ signsin the same expression, and it would mean that you're looking for astring with which your variable would both starts and end. Forinstance:

"hello world"=~ /^hello world$/ returns true because "hello world"starts and ends with "hello world".
"helloworld" =~ /^hello$/ returns false, because although"hello world" starts with "hello" it doesn't endwith it..

Note that there is no much point using both ^ and $in the same expression. If you're string starts and ends withsomething it is likely to be equal to that something... if you wantto test the equality of two strings, you can simply use the eqoperator:

"hello world"eq "hello world" returns true because the twostrings are identical.

The ne operator tests the non-equalityof two strings. It returns true if the strings are different andfalse otherwise:

"helloworld" ne "good night" returns true.

"helloworld" ne "Hello worlD" returns true (remember that Perlis case-sensitive)

"helloworld" ne "hello world" returns false because bothstrings are the same.

Remember to use the eq and ne operatorsto test the equality of strings in Perl, and their equivalence == and!= to test numerical values.
The !~ operator

The !~ operator is used as a �does not contain� operator. What!= is to ==, ne is to eq and !~ is to =~. For instance:

"hello world" !~ "world"returns false because �hello world� does contain �world�.

"hello world" !~ "wwt"returns true because �hello world� does not contain �wwt�.
Case insensitive search

When you use the =~ operator you test the matching of a stringwithin another, this is always case sensitive. For instance:

"hello world" =~ "world"returns true.

"hello world" =~ "woRld"returns false.

If you want to make the =~ operator insensitive, add an �i�after the expression:

"hello world" =~ /world/ireturns true.

"hello world" =~ /woRld/ialso returns true.
Substitutions

The =~ operator can also be used to find occurrences of a stringwithin a variable and substitute them with another string. Forinstance, if you have a variable which contains text, and you want tochange all occurrences of �aaa� with �aab� within that text,you can simply use the following substitution:

$variable =~ s/aaa/aab/;

All occurrences of �aaa� within $variable will then be changedto �aab�. Note that we prefixed our expression with an �s� tochange the meaning of the operator from �contains� to�substitute�.
Parsing files

There are many ways to parse a text file. In Perl, if the file hasits data organized line by line with delimiters, it is very easy toparse it.

Let's study a simple example. We have a set of employees in a filecalled employees.txt. In this file, each line represents an employee.The information relative to each employee is delimited with tabs, thefirst column is the name of the employee, the second column indicateshis department and the third one his salary. Here is an overview ofthe file:

Mr John Doe R&D 21000
Miss Gloria Dunne HR 23000
Mr Jack Stevens HR 45000
Mrs Julie Fay R&D 30000
Mr Patrick Reed R&D 33000

In order to obtain some statistics, the HR department wants toestablish a list of all male employees who work in the R&Ddepartment and which salary is more than 25000.

To obtain this list, we design a simple Perl script, which:

1.

opens the employees.txt file
2.

loops through each line
3.

identifies the name, department and salary of the employee
4.

ignores and goes to the next line if the employee is female (the name does not start with Mr)
5.

ignores and goes to the next line if the salary is less or equal to 25000.
6.

ignores and goes to the next line if the department is not �R&D�.
7.

prints the name and the salary of the employee on the screen.

To do this, we'll introduce two Perl functions:

*

�chomp� is used to remove the carriage return found in the end of the line. For instance chomp $variable removes all carriage returns in the variable.
*

�split� is used to cut the line in different parts where it finds a delimiter. For instance split /o/, �hello world� returns an array containing �hell�, � w� and �rld�. In our example we'll split the lines with the tab delimiter, which in Perl is written �\t�.

Here is the script which establishes the list of male employeesfrom the R&D department with a salary greater than 25000. To makethings a bit clearer, comments were introduced within the scripts(comments in Perl start with a # sign):

#open the employeesfile
open (EMPLOYEES,"employees.txt");

#for each line
while ($line =) {

#remove thecarriage return
chomp $line;

#split the linebetween tabs
#and get thedifferent elements
($name,$department, $salary) = split /\t/, $line;

#go to the nextline unless the name starts with "Mr "
next unless$name =~ /^Mr /;

#go to the nextline unless the salary is more than 25000.
next unless$salary > 25000;

#go to the nextline unless the department is R&D.
next unless$department eq "R&D";

#since allemployees here are male,
#remove theparticle in front of their name
$name =~ s/Mr//;

print"$name\n";
}
close (EMPLOYEES);

Study the script carefully and makesure you understand every part of it. Each instruction was eitherexplained in this lesson or in one of the previous ones. If you haveany question, do not hesitate to ask.

In the next lesson we'll look at how tointeract with the filesystem and the Linux operating system from ourPerl scripts.

Learn Perl in 10 lessons Lesson 3



What are If statements and loops?

Every Perl script is made of instructions which tell theinterpreter what to do. Depending on the purpose of the script you'llwrite different instructions. Sometimes, you might want someinstructions to be executed only on certain conditions. To do this,you'll use If statements. A typical If statement is aninstruction which defines three elements:

*

A condition
*

A set of instruction to execute if the condition is met
*

A set of instruction to execute if the condition is not met

For instance,consider the following code:

if ($time > 12){
print "Good Afternoon";
}
else {
print"Good Morning";
}


In this Ifstatement, the condition is ($time > 12). If the condition is metthen the script prints "Good afternoon", otherwise itprints "Good morning".

Sometimes, you might wantsome instructions to be executed more than once. For this you can useloops. A typical loop is composed of a condition and a set ofinstructions to execute. There are different kinds of loops and wewill study them in the chapters below.
If statements in Perl

Perl is a very flexible language and this is particularly truewhen it comes to If statements.
Simple If-statements

The most common form of If statement in programming is composed ofa condition (between parenthesis) followed by a set of instructionswhich are placed between brackets. For instance:

if ($time > 12) {
print "time is $time\n";
print"Good Afternoon\n";
}


Although it is considered bad practice, you don't have towrite the brackets if there is only one instruction in the Ifstatement:

if ($time > 12)
print "Good Afternoon\n";

To avoid any possible confusion, it is recommended to always writethe brackets, or, if there is only one simple instruction to placethe condition and the instruction on the same line:

if($time > 12) print "Good Afternoon\n";

In Perl, you can also write the condition after the instructionitself. For instance:

print "Good Afternoon\n" if($time > 12);
Else and Elsif Statements

Similarly, you can define an �else� block of instructions,which will be executed if the condition is not met:

print"time is $time\n";
if ($time > 12) {
print "GoodAfternoon\n";
}
else {
print "Good Morning\n";
}

Sometime you may want to dosomething depending on more than one condition. Of course you canalways define If statement within others, but you can also use elsif,as a contraction of �else, if (something else..)�:

if ($time < 12) {
print "GoodMorning\n";
}
elsif ($time < 20) {
print "Good Afternoon\n";
}
elsif ($time < 23) {
print "Good Evening\n";
}
else {
print "Good night\n";
}
Unless-statements

In Perl, you can use the Unlessstatement. It behaves exactly like the If statement but executes thecode if the condition is not met. For instance the following codeprints �Good night� if it's more than 11pm:

print "Good night\n" unless($time < 11pm);
Loops in Perl

There are many different kinds of loop in Perl. Here are the mostcommon types.
While loop

This loop executes a block of code while a condition remains true.For instance, the following code prints �Hello� three times:

$i = 0;
while ($i < 3) {
print "Hello\n";
$i = $i + 1;
}
Until loop

This loop executes a block of code until a condition becomes true.For instance, the following code prints �Hello� three times:

$i = 1;
until ($i > 3) {
print "Hello\n";
$i = $i + 1;
}
For loop

The for loop is composed of four elements:

*

A starting assignment
*

A condition
*

An incrementation
*

A set of instructions

The notation of the For-loop is as follows:

for (starting assignment; condition; incrementation) {
instructions
}

The for loop starts by executing the starting assignment. Then,while the condition is met, it keeps executing the instructions andthe incrementation. For instance the following For-loop prints�Hello� three times:

for ($i = 0; $i < 3; $i = $i + 1) {
print "Hello\n";
}

Note that the ++ operator is usually used to increment a variable,so we could have written $i++ instead of $i = $i + 1;

In Perl, you can also use the For-loop with a �range operator�.The notation for the range operator is �..�. For instance, thefollowing code prints �Hello� three times:

for (1..3) {
print "Hello\n";
}
Foreach loop

The foreach loop is used to iterate through the elements of anarray. For instance, the following code prints the days of the week:

@days = ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday");
foreach $dayOfTheWeek (@days) {
print "$dayOfTheWeek\n";
}

You can also use the foreach loop to iterate through the keys of anhashtable. For instance, the following code prints the days of theweek:

%days = ();
$days{"Monday"} = 1;
$days{"Tuesday"} = 2;
$days{"Wednesday"} = 3;
$days{"Thursday"} = 4;
$days{"Friday"} = 5;
$days{"Saturday"} = 6;
$days{"Sunday"} = 7;

foreach $day (keys %days) {
print "$day is the day number $days{$day} of the week\n";
}
File Handling

The Perl language was designed to make file handling easy andefficient, so you'll probably won't have any problem opening filesand reading them.
Opening and closing files

In order to open a file, you'll use the �open� instructionwhich takes two arguments: the name of a filehandle and the name ofthe file itself. The filehandle is like a variable which representsthe handling of the file within the script. For instance, in thefollowing code we're opening the file �clients.txt� with afilehandle called CLIENTS:

open (CLIENTS, "clients.txt");

By default, the file is open in read-mode, which means you canonly read from it. You can decide to open a file in write-mode, inorder to be able to write into it. If the file already existed or hadsome data written into it, the data will be lost. To open a file inwrite-mode simply add a �>� in front of the file name:

open (CLIENTS, ">clients.txt");

If you'd rather keep the data written in the file, you can openthe file in append-mode. This way, the data will be kept, and whatyou'll write in the file will be appended to it. In order to do thisadd a �>>� in front of the file name:

open (CLIENTS, ">>clients.txt");

The �open� instruction returns true if it managed to open thefile, false otherwise. You can use this value in order to test thesuccess of the operation. For instance, the following code opens thefile in write-mode and prints �Insufficient privileges� if thescript doesn't manage to do so.

open (CLIENTS, ">clients.txt") or print "Insufficientprivileges\n";

Remember to always close the files once you're finished with them.If you don't your changes might be lost. In order to close a file,simply use the �close� instruction on the filehandle:

close (CLIENTS);
Writing into files

Once the file is open in write mode you can write into it simplyby writing into its filehandle. The �print� instruction writesthings on the screen by default, but you can specify a filehandle towrite into. For instance, the following code adds a line �Mr JohnDoe� in the end of the �clients.txt� file:

open (CLIENTS, ">>clients.txt") or die "Insufficientprivileges\n";
print CLIENTS "Mr John Doe\n";
close (CLIENTS);
Reading data from files

There are many ways to read the content of a file. Here are thetwo most common ways in Perl.
Copying the content of the file into an array

You can copy the whole content of the file into an array. Eachline will then correspond to an element of the array. Here is anexample:

open(CLIENTS, "clients.txt");
@lines = ;
close(CLIENTS);
print @lines;

Looping through the filehandle

Alternatively you can loop through the filehandle in a while loopby writing while($line = ) (think of it as �whilethere are lines in the clients file, I'm assigning the current lineto $line):

open (CLIENTS, "clients.txt");
while ($line = ) {
print $line;
}
close (CLIENTS);

As you can see, Perl makes it very easy to manipulate files. Inthe next lesson we'll look at how to search for a particular elementwithin a file, and how to handle and manipulate strings.

Learn Perl in 10 lessons Lesson 2


What are variables?

Variables are used in every computer language. If you are new to programming, remember the variables used in algebra equations. For instance, consider the following equation:

a + 5 = 7

In this equation, there is only one variable. Its name is "a" and its value is "2". Variables always have a name and they always have a value. In algebra their value is usually a number. In programming, their value can be a number, a character, a string (which means a sequence of characters), or even a complex object such as an array, a hashtable, a data structure, etc... Throughout the lessons we will use variables to store many different types of objects or values and you will become more familiar with the different data types that a variable can represent.
Variables in Perl

In Perl, there a three types of variables: * scalar variables, * arrays, * hashtables.

Scalar variables store a single value. In Perl, scalar variables names are always prefixed with a dollar sign. For instance:

$a = 2;

$message = "Hello World!";

Arrays can store many values. In Perl, arrays are always prefixed with an at-sign. For instance:

@colors = ("red", "green", "blue");@primaryNumbers = (1, 2, 3, 5, 7);

Hashtables are a special kind of array: associative arrays. They are like arrays, but for each of the value they store, they also store a corresponding name or label. They consist of pairs of elements - a key and a data value. In Perl, hashtables are always prefixed with a percent sign. For instance:

%phoneNumbers = (Alicia => "090-64-773315", Tom => "085-153-3214", Jimmy => "085-285-4545");

In this lesson we will focus on scalar variables and arrays. They are simple to use and they will help us write our calculator.
What are command line arguments?

In the previous lesson we first called our script by invoking the Perl interpreter:

perl myScript.pl

Then we saw how to make an implicit call to the interpreter so that the script could be called directly:

./myScript.pl

Whether we call the interpreter implicitly or explicitly, we can give arguments to the script. These arguments are given while calling the script, and simply put after the script name:

./myScript.pl argument1 argument2 argument3

For instance, instead of having a script which writes "Hello World!" on the screen, and thus doesn't need any argument, we will write a calculator in this lesson. Our calculator will calculate the result of a simple equation which we will give as a command line argument. For instance, if we wanted our calculator to add 5 and 6, we would call it like this:

./calculator.pl 5 + 6

In this example, we gave three command line arguments:

* 5
* +
* 6

The Perl script will have to look at these arguments, identify the second argument to know what operation to do with the first and third arguments, calculate and print the result on the screen. Command line arguments in PerlWhen the interpreter runs the Perl script it stores the command line arguments in an array called @ARGV. Note that the Perl language is case-sensitive, so it is important to use capital letters here. @ARGV is an array, and like every array in Perl you can do the following on it:

* Get the first element of the array by typing $ARGV[0] (note that as this is a single value it is represented by a scalar variable and prefixed with a dollar sign).
* Get the second elements of the array by typing $ARGV[1]... etc.
* Get the index of the last element in the array by typing $#ARGV.

Note that arrays always start from 0, not from 1. Therefore the first element of an array, is element 0, not element 1. For instance element number 12 corresponds to the 13th element of an array. This is a convention in many programming languages. The index of the last element in the array corresponds to the number of elements - 1.

In our example, we call our calculator by giving it three arguments:

./calculator.pl 5 + 6

Therefore we can expect the @ARGV array to contain three elements, $#ARGV being equal to 2 and $ARGV[0], $ARGV[1] and $ARGV[2] respectively being equal to 5, "+" and 6.
Your second Perl script, the Calculator!

You nearly know everything you need in order to code your second Perl script and to write a nice calculator. In fact you could do it yourself now! As we said before, there are more than one way to do something in Perl. Try to program the calculator by yourself, and then have a look at the solution below.

Create a file called calculator.pl and write the following into it:

#!/usr/bin/perl$nbArguments = $#ARGV + 1;print "number of arguments: $nbArguments\n";exit(1) unless $nbArguments == 3;$a = $ARGV[0];$b = $ARGV[2];$operation = $ARGV[1];if ($operation eq "+") { $result = $a + $b;}elsif ($operation eq "-") { $result = $a - $b;}elsif ($operation eq "/") { $result = $a / $b;}elsif ($operation eq "x") { $result = $a * $b;}print "$a $operation $b = $result\n";

Make the script executable:

chmod a+rx calculator.pl

Run the script :

./calculator.pl 5 + 6./calculator.pl 11 - 2./calculator.pl 4 x 3./calculator.pl 33 / 3

The script works as expected, but there probably are a lot of instructions you didn't fully understand within this script. So let's look at them.

The first line tells where to find the interpreter, so that we can call the script directly.

The second line takes the index of the last element from the @ARGV array and adds 1 to it. That way it gets the number of command line arguments given to the script and stores it in a variable called $nbArguments.

The third instruction simply prints the number of arguments on the screen.

There is a lot to say about the fourth instruction (exit(1) unless $nbArguments == 3:

* "exit" is a Perl function which makes the script stop and return a given code to the shell. In this example the script stops and returns 1 to the shell. 1 is a Unix convention which means that there was an error.
* "unless" is the opposite of "if". These are Perl statements. In this example, "exit" is called unless the following statement is true "$nbArguments == 3".
* In Perl, and in many programming languages, the equal sign is used to affect values to variables. For instance, when we wrote $nbArguments = $#ARGV + 1, we assigned a value to $nbArguments. The double equal sign "==" is a comparison operator which returns true or false depending on the fact that the variables or values on both side are equal or not. Perl also provides another operator "eq" which compares strings. Try to use "eq" for string comparisons and "==" for numbers. Remember that the "=" sign assigns values and is not a comparison operator.
* In brief, (exit(1) unless $nbArguments == 3 means that the script will stop unless three command line arguments were given.

The three next instructions simply assign the three command line arguments to variables. We stored the first one in $a, the third one in $b and the second on in $operation.

Then, depending on the value of $operation, we made a different calculation with $a and $b and stored the result in a variable called $result. Note that we used "if" and "elsif" statements. We will come back to these statements later, but for the moment remember that "elsif" is a contraction for "else if...". Also, note that we used brackets to clearly identify blocks of code between the if statements and that we indented our code. In general, unless you have a very simple one liner to write, use brackets for each if statement and always indent your scripts.

The last instruction writes a summary of the operation and its operands as well as the result on the screen.

In this lesson we learnt how to use variables and command line arguments. We also had a quick look at If statements, comparisons operator and a few operations. In the next lesson, we'll manipulate text files and go a bit further in using operators and other statements.