What is Perl?
From the official docs:
"Perl officially stands for Practical Extraction and Report Language, except when it doesn't."
It's a general purpose programming language developed for manipulating texts mainly. It has been used to perform system administration tasks, networking, building websites and more.
What data types Perl has? And how can we define it?
- Scalar: This is a simple variable that stores single data items. It can be a string, number or reference.
my $number = 5;
- Arrays: This is a list of scalars.
my @numbers = (1, 2, 3, 4, 5);
# or using the `qw` keyword (quote word):
my @numbers = qw/1 2 3 4 5/;
# '/' can be another symbol, e.g qw@1 2 3 4 5@
- Hashes (or associative arrays): This is an unordered collection of key-value pairs. We can access to a hash using the keys.
my %numbers = (
First => '1',
Second => '2',
Third => '3'
);
How can you access to a hash value, add and delete a key/value pair and modify a hash?
my %numbers = (
'First' => '1',
'Second' => '2',
'Third' => '3'
);
- Access:
print($numbers{'First'});
- Add:
$numbers{'Fourth'} = 4;
- Delete:
delete $numbers{'Third'};
- Modify:
$numbers{'Fifth'} = 6;
$numbers{'Fifth'} = 5;
How can you iterate an array? And a hash?
- Array:
my @numbers = qw/1 2 3 4 5/;
# Using `$_` that represents the current iteration in a loop. It starts from index array 0 until the last index.
foreach (@numbers) {
print($_);
}
# Output: 12345
# "$#" returns the max index of an array. That's the reason because we can iterate accessing to the array from the index 0 to the max index.
for my $i (0..$#numbers) {
print($numbers[$i]);
}
# Output: 12345
# Using the `map` keyword:
print map {$_} @numbers;
# Output: 12345
# Using `while`. We should take care with this option. When we use `shift` we're deleting the first element of the array and assigning it to the `element` variable.
# After this `loop` the `numbers` array will not have elements.
while (my $element = shift(@numbers)) {
print($element);
}
# Output: 12345
- Hashes:
my %capital_cities = (
'Madrid' => 'Spain',
'Rome' => 'Italy',
'Berlin' => 'Germany'
);
# Iterate and get the `keys`:
foreach my $city (keys %capital_cities) {
print($city . "\n");
}
# Iterate and get the `values`:
foreach my $country (values %capital_cities) {
print($country . "\n");
}
# Iterate and get the values and keys (first option):
foreach my $city (keys %capital_cities) {
print("City: $city - Country: $capital_cities{$city}" . "\n");
}
# Iterate and get the values and keys (first option):
while(my ($city, $country) = each %capital_cities) {
print("City: $city - Country: $capital_cities{$city}" . "\n");
}
What is a Perl subroutine? How to define it?
It's the perl model for user defined functions (this is also called function like other programming languages). We can define a subroutine with the keyword sub
.
sub hello {
print "hello";
}
Describe the different ways to receive parameters in a subroutine
- List assignment: Using the
@_
array. It's a list with the elements that are being passed as parameters.
sub power {
my ($b, $e) = @_;
return $b ** $e;
}
&power(2, 3);
- Individual assignment: We should access to every element of the
@_
array. It starts from zero.
sub power {
my $b = $_[0];
my $e = $_[1];
return $b ** $e;
}
&power(2, 3);
- Using
shift
keyword: It's used to remove the first value of an array and it's returned.
sub power {
my $b = shift;
my $3 = shift;
return $b ** $e;
}
&power(2, 3);
We can also read the best way in the same S.O answer.
What is lexical and dynamic scoping?
How to apply referencing and dereferencing?
What is Perl POD? Can you code an example?
From the official docs:
"Pod is a simple-to-use markup language used for writing documentation for Perl, Perl programs, and Perl modules."
=item
This function returns the factorial of a number.
Input: $n (number you wanna calculate).
Output: number factorial.
=cut
sub factorial {
my ($i, $result, $n) = (1, 1, shift);
$result = $result *= $i && $i++ while $i <= $n;
return $result;
}
Check if the word `electroencefalografista` exists in a string
my $string = "The longest accepted word by RAE is: electroencefalografista";
if ($string =~ /electroencefalografista/) {
print "Match!";
}
Check if the word `electroencefalografista` does not exists in a string
my $string = "The longest not accepted word by RAE is: Ciclopentanoperhidrofenantreno";
if ($string !~ /electroencefalografista/) {
print "Does not match!";
}
Replace the word `amazing`
my $string = "Perl is amazing!";
$string =~ s/amazing/incredible/;
print $string;
# Perl is incredible!
Extract `hh:mm:ss` with capturing group `()` in the following datetime
my $date = "Fri Nov 19 20:09:37 CET 2021";
my @matches = $date =~ /(.*)(\d{2}:\d{2}:\d{2})(.*)/;
print $matches[1];
# Output: 20:09:37
Extract all the elements that are numbers in an array
my @array = ('a', 1, 'b', 2, 'c', 3);
my @numbers = grep (/\d/, @array); # Note: \d involves more digits than 0-9
map {print $_ . "\n" } @numbers;
Print all the linux system users that starts with d or D
- With a Perl one liner :D
open(my $fh, '<', '/etc/passwd');
my @user_info = <$fh>;
map { print $& . "\n" if $_ =~ /^d([^:]*)/ } @user_info;
close $fh;
- Avoiding one-liners
foreach my $user_line (@user_info) {
if ($user_line =~ /^d([^:]*)/) {
print $& . "\n";
}
}
Mention the different modes in File Handling
- Read only:
<
- Write mode. It creates the file if doesn't exist:
>
- Append mode. It creates the file if doesn't exist:
>>
- Read and write mode:
+<
- Read, clear and write mode. It creates the file if doesn't exist:
+>
- Read and append. It creates the file if doesn't exist:
+>>
How to write into a file?
# We can use:
# '>' Write (it clears a previous content if exists).
# '>>' Append.
open(my $fh, '>>', 'file_name.ext') or die "Error: file can't be opened";
print $fh "writing text...\n";
close($fh);
How can you read a file and print every line?
open(my $fh, '<', 'file_to_read.ext') or die "Error: file can't be opened";
my @file = <$fh>;
foreach my $line (@file) {
print $line;
}
We can use the file handle without assigning it to an array:
open(my $fh, '<', 'file_to_read.ext') or die "Error: file can't be opened";
foreach my $line (<$fh>) {
print $line;
}
Does Perl have support for OOP?
From the official docs:
"By default, Perl's built-in OO system is very minimal, leaving you to do most of the work."
What is the purpose of the bless function?
The function os the bless
function is used to turning a plain data structure into an object.
How to create a Perl class? How can you call a method?
- Let's create the package:
Example.pm
package Example;
sub new {
my $class = shift;
my $self = {};
bless $self, $class;
return $self;
}
sub is_working {
print "Working!";
}
1;
- Now we can instance the
Example
class and callis_working
method:
my $e = new Example();
$e->is_working();
# Output: Working!
Does Perl have inheritance? What is the `SUPER` keyword?
Yes, Perl supports inheritance. We can read about it in the official docs.
We also can read about SUPER
keyword that is used to call a method from the parent class. It gives an example about how we can apply inheritance.
Does Perl have polymorphism? What is method overriding?
Yes, it has polymorphism. In fact method overriding is a way to apply it in Perl.
Method overriding in simple words appears when we have a class with a method that already exist in a parent class.
Example:
package A;
sub new { return bless {}, shift; };
sub printMethod { print "A\n"; };
package B;
use parent -norequire, 'A';
sub new { return bless {}, shift; };
sub printMethod { print "B\n"; };
my $a = A->new();
my $b = B->new();
A->new()->printMethod();
B->new()->printMethod();
# Output:
# A
# B
How can you call a method of an inherited class?
# Class `A` with `printA` method.
package A;
sub new { return bless {}, shift; };
sub printA { print "A"; };
# Class `B` that extends or use the parent class `A`.
package B;
use parent -norequire, 'A';
sub new { return bless {}, shift; };
# Instance class `B` allows call the inherited method
my $b = B->new();
$b->printA();
How can we evaluate and capture an exception in Perl?
From the official eval docs:
"eval
in all its forms is used to execute a little Perl program, trapping any errors encountered so they don't crash the calling program.".
e.g:
eval {
die;
};
if ($@) {
print "Error. Details: $@";
}
If we execute this we get the next output:
Error. Details: Died at eval.pl line 2.
The eval
(try
in another programming languages) is trying to execute a code. This code fails (it's a die), and then the code continues into the if
condition that evaluates $@
error variable have something stored. This is like a catch
in another programming languages. At this way we can handle errors.
What is Perl Open3?
From the official IPC::Open3 docs:
"IPC::Open3 - open a process for reading, writing, and error handling using open3()".
With open3
we can have the full control of the STDIN, STDOUT, STDERR. It's usually used to execute commands.
Using Open3: Create a file with the size of 15MB and check it's created successfully
- Code:
use IPC::Open3;
use Data::Dumper;
sub execute_command {
my @command_to_execute = @_;
my ($stdin, $stdout, $stderr);
eval {
open3($stdin, $stdout, $stderr, @command_to_execute);
};
if ($@) {
print "Error. Details: $@";
}
close($stdin);
return $stdout;
}
my $file_name = 'perl_open3_test';
&execute_command('truncate', '-s', '15M', $file_name);
my $result = &execute_command('stat', '-c', '%s', $file_name);
print Dumper(<$result>);
- Result:
$ -> perl command.pl
$VAR1 = '15728640
';
What is a Perl package? And a module?
With a Perl package we are defining a namespace.
A Perl module in one simple word can be defined as a class
. When we create a class
in Perl we use the package
keyword. A module can be used with the use
keyword.
What is the difference between .pl and .pm extensions?
There's no a real difference between a .pm
and .pl
extensions. Perl use .pm
extensions just to difference it as a perl module (a class). .pl
extensions are usually named for perl scripts without OOP classes.
Why a Perl class (or module) should return something at the end of the file? Check the example.
If we want to use
a Perl module (import
a class), this module should end in a value different than 0. This is necessary because if we try to import the class and it has a false value, we will not be able to use it.
package A;
sub new { return bless {}, shift; };
sub printMethod { print "A\n"; };
1;