## Perl
### Perl Self Assessment
What is Perl?
From the official [docs](https://perldoc.perl.org/):
"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 accesing 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 subroute 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 assigment: 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);
```
[Source](https://stackoverflow.com/a/21465275/12771230)
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?
Does Perl have conventions?
You can check [perlstyle](https://perldoc.perl.org/perlstyle)
What is Perl POD? Can you code an example?
From the official [docs](https://perldoc.perl.org/perlpod):
"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;
}
```
### Perl Regex
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";
}
}
```
### Perl Files Handle
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;
}
```
### Perl OOP
Does Perl have support for OOP?
From the official [docs](https://perldoc.perl.org/perlootut):
"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 call `is_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](https://perldoc.perl.org/perlobj#Inheritance).
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 inherated method
my $b = B->new();
$b->printA();
```
### Perl Exception Handling
How can we evaluate and capture an exception in Perl?
From the official [eval docs](https://perldoc.perl.org/functions/eval):
"`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.
### Perl OS
What is Perl Open3?
From the official [IPC::Open3 docs](https://perldoc.perl.org/IPC::Open3):
"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
';
```
### Perl Packages & Modules
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;
```
What is cpan? And cpanm?
How can you install a Perl module?