| |||
|
| |||
Perl Primer Exercisesby Linda NaughtonPrinting Decimal and HexStarting with $value1 = 255, print it out in decimal and hex.Then do the same thing with $value2 = "0xff" and $value3 = 0xff. What happens if you call the hex function with the decimal value 255? (Scroll down for answer) Source $value1 = 255; # Print in decimal - no processing necessary print $value1 . "\n"; # Print in hex - use printf. printf "0x%x\n", $value1; $value2 = "0xff"; # Print in decimal - must use the hex() function # to convert. print hex($value2) . "\n"; # Print in hex - no processing necessary print $value2 . "\n"; $value3 = 0xff; # Print in decimal - no processing necessary # due to perl auto-convert print $value3 . "\n"; # Print in hex - must use printf even though it # was declared in hex. printf "0x%x\n", $value3; # What happens if you call hex() with the decimal value # 255 or the equivalent hex value 0xff? They both print # 597 because you're telling perl to interpret the # resulting decimal value (255) as a hex number. print hex(255) . "\n"; print hex(0xff) . "\n";Output 255 0xff 255 0xff 255 0xff 597 597 Push vs ShiftCreate code that uses shift/unshift to do the following:Add 2 numbers, remove 1, add another, remove another. Print out the array after each step. Repeat the code using push/pop and observe the differences. (Scroll down for answer) Source my @array; my $value; print "----------------\n"; print "Using shift/unshift\n"; $value = 1; unshift(@array, $value); print "Adding $value: @array\n"; $value = 2; unshift(@array, $value); print "Adding $value: @array\n"; $value = shift(@array); print "Removing $value: @array\n"; $value = 3; unshift(@array, $value); print "Adding $value: @array\n"; $value = shift(@array); print "Removing $value: @array\n"; undef @array; print "----------------\n"; print "Using push/pop\n"; $value = 1; push(@array, $value); print "Adding $value: @array\n"; $value = 2; push(@array, $value); print "Adding $value: @array\n"; $value = pop(@array); print "Removing $value: @array\n"; $value = 3; push(@array, $value); print "Adding $value: @array\n"; $value = pop(@array); print "Removing $value: @array\n";Output ---------------- Using shift/unshift Adding 1: 1 Adding 2: 2 1 Removing 2: 1 Adding 3: 3 1 Removing 3: 1 ---------------- Using push/pop Adding 1: 1 Adding 2: 1 2 Removing 2: 1 Adding 3: 1 3 Removing 3: 1 Custom SortCreate a sort subroutine that will take the array (major, minor, major, minor) and sort the array so that all the "minor" items come before all the "major" items.(Scroll down for answer) Source
my @array = ("major", "minor", "major", "minor");
@array = sort sortMinorFirst (@array);
print @array;
sub sortMinorFirst
{
if ($a eq $b)
{
return 0;
}
# The lc is optional in this case, but in general
# is good to ensure that case-sensitivity doesn't
# matter.
elsif (lc($a) eq "minor")
{
return -1;
}
else
{
return 1;
}
}
Output
minorminormajormajorNote: We'll see how to print out the array in a nicer looking fashion in a later example. Creating HashesCreate a hash that stores hostname and IP address (either one can be the key; your choice). Initialize the array with at least 3 values and print the list of keys.(Scroll down for answer) Source
my %ipHash;
$ipHash{"192.168.1.1"} = "tornado";
$ipHash{"192.168.1.13"} = "omeara";
$ipHash{"192.168.1.156"} = "doc1";
print keys(%ipHash);
Output
192.168.1.1192.168.1.13192.168.1.156Note: We'll learn how to print out the hash in a nicer looking fashion in a later example. While LoopCreate a while loop that will create an array containing all of the EVEN numbers between 1 and 10, in order from least to greatest. Then remove them each from the array and print them. Try it again with the numbers between 0 and 10. Why doesn't this work?(Scroll down for answer) Source
my @evenNumbers;
my $i = 1;
while ($i <= 10)
{
if ($i % 2 == 0)
{
push(@evenNumbers, $i);
}
$i++;
}
while ($i = shift(@evenNumbers))
{
print "$i ";
}
Output
2 4 6 8 10Why doesn't it work if you go from 0 to 10? Because the first time through the second while loop, "i" is 0. The while loop fails. You could get around this using the same logic as the original loop (while ($i = shift(@evenNumbers)) < 10) but a better way to do this is using a foreach loop. Foreach LoopCreate a hash that stores the hostname, IP address, and domain name (use IP address as the key). Initialize it with at least 3 elements. Print out a table in the form: IP HOST DOMAIN showing all of the items in order of ascending IP addresses.(Scroll down for answer) Source
my $ip;
my %ipHash;
$ipHash{"192.168.1.1"}{"HOST"} = "doc";
$ipHash{"192.168.1.13"}{"HOST"} = "happy";
$ipHash{"192.168.1.156"}{"HOST"} = "grumpy";
$ipHash{"192.168.1.1"}{"DOMAIN"} = "testnet";
$ipHash{"192.168.1.13"}{"DOMAIN"} = "mednet";
$ipHash{"192.168.1.156"}{"DOMAIN"} = "testnet";
print "IP HOST DOMAIN\n";
# The default sort works fine for sorting IP addresses,
# since they are like strings.
foreach $ip (sort keys %ipHash)
{
print "$ip\t";
print $ipHash{$ip}{"HOST"};
print "\t";
print $ipHash{$ip}{"DOMAIN"};
print "\n";
}
Output
IP HOST DOMAIN 192.168.1.1 doc testnet 192.168.1.13 happy mednet 192.168.1.156 grumpy testnetNote: Even with tabs, this may not line up quite right. You would have to use the printf function (or something similar) to get it to print perfectly. Creating a SubroutineCreate a subroutine that adds an array of numbers (passed to it) and returns the result.(Scroll down for answer) Source
my @array = (1, 2, 5, 10);
my $sum;
$sum = addNumbers(@array);
print "The sum is: $sum\n";
sub addNumbers
{
my (@numberList) = @_;
my $sum = 0;
my $i;
foreach $i (@numberList)
{
$sum += $i;
}
return $sum;
}
Output
The sum is: 18 Passing Parameters by ReferenceCreate a subroutine that takes an array reference and appends a value (passed to it) to the array. Print the resulting array.(Scroll down for answer) Source
my @array = (1, 2, 10);
my $item;
# Use \ to pass the array by reference.
appendToArray(\@array, 77);
foreach $item (@array)
{
print "$item ";
}
sub appendToArray
{
my ($arrayP, $value) = @_;
# Use @$ to dereference it as an array.
push(@$arrayP, $value);
}
Output
1 2 10 77 Command Line InputUsing the options package, create a script that accepts Šval1 and Šval2 as options and prints out the sum of the two values. If either value is missing, it prints an error.(Scroll down for answer) Source
use Getopt::Long;
my $opt_val1;
my $opt_val2;
unless(GetOptions("val1=i" => \$opt_val1,
"val2=i" => \$opt_val2))
{
die "Couldn't parse options.\n";
}
if (!defined($opt_val1) or !defined($opt_val2))
{
die "Missing required options.\n";
}
print "Sum = ";
print $opt_val1 + $opt_val2;
Output
c:\>test.pl -val1=2 -val2=4 Sum = 6 Reading a Text FileOpen a text file for input, read in its contents, and print out line 5.(Scroll down for answer) Source open(INFILE_HANDLE, "in.txt") or die "Error opening infile: $!\n"; @fileContents =Output (assuming the text file has "line1, line2, line3, etc." as its contents) line 5 Output to a FilePrompt the user for a filename, and print the numbers 1 through 10 to that file.(Scroll down for answer) Source my $fileName; my $i; print "Enter filename: "; $fileName =Output Enter filename: out.txt Done! Regexp BasicsCreate a script that will prompt the user for a string and tell them whether it contains "fred" (case-insensitive). Test it with strings including Fred, Frederick, wilma and Alfred.(Scroll down for answer) Source my $string; print "Enter string to compare: "; $string =Output Enter string to compare: Frederick Frederick contains fred!Why does it print out with a linebreak after Frederick? Because strings obtained from the diamond operator ( Regexp WildcardsCreate a script that will prompt the user for a string and tell them whether it matches foo, followed by any character (except newline), followed by any whitespace character, followed by bar. Test with strings including foobar, fooa bar, and foo9 bar.(Scroll down for answer) Source my $string; print "Enter string to compare: "; $string =Output Enter string to compare: fooa bar fooa bar matches! Regexp QuantifiersCreate a script that will prompt the user for a string and tell them whether it contains at least one a followed by any number (including 0) of b's. Test with strings including barney, fred, abba, and dinosaur.(Scroll down for answer) Source my $string; print "Enter string to compare: "; $string =Output Enter string to compare: abba abba matches! Regexp Character ClassesCreate a script that will prompt the user for a string and tell them whether it contains a valid hex string (such as 0xaa or 0x2b7f). The 0x is required and any number of hex characters may follow.(Scroll down for answer) Source my $string; print "Enter string to compare: "; $string =Output Enter string to compare: 0xmf 0xmf doesn't match! Enter string to compare: 0xa8 0xa8 matches!Note: This will match seemingly invalid hex strings, like 0xa8mz because they start with a valid hex string (even though there's junk after it). We'll learn how to avoid that when we talk about anchors. Regexp GroupsCreate a script that will read lines from a file and print out lines that match the pattern: SEVERITY/TYPE, where defect can be either "MAJ" or "MIN", and type can be one or more alphanumeric characters. Run it on a file containing:MAJ/DOC MIN/COD MAJ/ MAJOR/LOG MAJ/DOC/ AbcMAJ/DOC (Scroll down for answer) Source open(INFILE_HANDLE, "in.txt") or die "Can't open infile: $!\n"; while ($line =Output Line matches: MAJ/DOC Line matches: MIN/COD Regexp AnchorCreate a script that will match a hex string (0xff with any number of digit chars) but won't match hex strings inside other strings (i.e. it won't match bob0xff or 0xffred).
Extra credit: Modify the script so it will match a string that contains
multiple hex strings separated by spaces (0xff 0x123 0xab etc.)
my $string; print "Enter string to compare: "; $string =Output Enter string to compare: 0xff 0xff matches! Enter string to compare: bob0xff bob0xff doesn't match! Enter string to compare: 0xffred 0xffred doesn't match!Extra credit: Change the regexp to this (which uses word boundary anchors instead of string anchors, and requires a space after the whole group of hex chars): if ($string =~ /(\b0x[0-9a-f]+\b)\s/i) Regexp MemoryCreate a script that matches SEVERITY/TYPE (like in the previous example), but this time store the severity and type in local variables. Print them out (Severity: [severity], Type: [type]) instead of just printing out the line that matched.(Scroll down for answer) Source open(INFILE_HANDLE, "in.txt") or die "Can't open infile: $!\n"; while ($line =Output Severity: MAJ, Type: DOC Severity: MIN, Type: COD Regexp SubstitutionsCreate a script that matches two words and swaps their order. For example: match "green scaly dinosaur" and replace with "scaly green dinosaur".(Scroll down for answer) Source $string = "green scaly dinosaur"; print "Original string: $string\n"; $string =~ s/(\w+) (\w+)/$2 $1/; print "Modified string: $string\n";Output Original string: green scaly dinosaur Modified string: scaly green dinosaur Test PackageCreate a package that will let you get and set a single member variable. Also create a wrapper/driver to create the package, set the variable, get the variable, and print the result.(Scroll down for answer) Source
Driver code (test.pl):
use TestPackage;
my $TestPackage = new TestPackage();
$TestPackage->setTestValue(77);
print $TestPackage->getTestValue();
Package code (TestPackage.pm):
package TestPackage;
use strict;
use constant M_TEST_VALUE => "m_testValue";
sub new
{
my ($garbage) = @_;
my $selfP = {};
bless $selfP;
return $selfP;
}
sub setTestValue
{
my ($selfP, $testValue) = @_;
$selfP->{M_TEST_VALUE} = $testValue;
}
sub getTestValue
{
my ($selfP) = @_;
return $selfP->{M_TEST_VALUE};
}
1;
Output
77 |
![]()
|
||