1a. Scalar: string

Perl has three main data types: $scalar, @array (chapter 4), and %hash (chapter 1, part 2). A Scalar represents a Single value. A scalar variable - a name preceded by the '$' sigil like the character 'S' - contains a single value. A string or a number are examples of a single value or a scalar. Now something about strings.

1.1 Create

The declaration of a scalar:
$abc = "abc";
$def = "def";
Strings can be concatenated by the dot (.) operator:
$str = "abc" . " " . "cde"; # $str has the value 'abc cde'
where strings can be replaced by variables:
$abc = "abc";
$str = $abc . " " . "cde"; # $str has the value 'abc cde'
Concatenation is often useful for readability. However, it is not always necessary. Variable interpolation ( = replacing a variable with the value of that variable) can give correct results:
$abc = "abc";
$cde = "cde";
$str = "$abc $cde"; # $str has the value 'abc cde'
Shorthand with the .= operator:
$str = "abc" . " ";
$str .= "cde"; # $str has the value 'abc cde'
A scalar variable can be defined by other scalar variables:
$bird = "penguin";
$no_of_birds = "two";
$bird_type = $bird; # $bird_type has now the value "penguin".
$observation = "I saw $no_of_birds ${bird}s."; # I saw two penguins.
You could not write here $birds, because the variable $birds does not exist. Hence curly braces ${bird}s are necessary in order to separate the character 's' from the variable name. The last example can be done with concatenation using the dot operator.
$bird_type = $bird; # $bird_type has now the value "penguin".
$observation = "I saw " . $no_of_birds . " " . $bird . "s."; # I saw two penguins.
You can assign a value to multiple variables:
($first, $second, $third, $fourth);
$first = $second = "one";
$third = $fourth = "two";
and swap the values easily:
($first, $third) = ($third, $first); # $first has the value 'two' and $third the value 'one'.
1.1.1 Short cuts q and qq
Four ways to get the same result...I prefer the third option.
$str = "Did you say \"Hello?\"\n"; # backslash necessary
$str = qq(Did you say "Hello?"\n);
$str = 'Did you say "Hello?"' . "\n";# my preferred option
$str = q(Did you say "Hello?") . "\n";
qq for double apostrophes (interpolation is possible) and q for a single one (for literally output). You can use pairs of delimiters of your choice like //, [], {} etc.

1.2 Access

For now, we can discern access tools for strings and numbers. In this chapter, we only discuss the (sub)string tools.
1.2.1 Extract a substring
$result = substr("abcdefgh", 2); # the value of $result is cdefgh; strings are zero-based, i.e. the first character has the index 0
$result = substr("abcdefgh", 2, 3); # the value of $result is cde
1.2.2 Find index of a substring (aka 'check if a string contains a substring')
Find the index of the first occurrence of the substring 'fo'.
$str = "From forth the fatal loins of these two foes";
$result = index($str, "fo"); # the value of $result is 5
Find the index of the second occurrence of the substring 'fo': add simply as third argument a start position to start searching.
$str = "From forth the fatal loins of these two foes";
$result = index($str, "fo", (5 + 2) ); # the value of $result is 40
If a substring is not found, index returns -1. Use rindex to start searching at the end of a string.
$str = "From forth the fatal loins of these two foes";
$result = rindex($str, "fo"); # the value of $result is 40
With a start position:
$str = "From forth the fatal loins of these two foes";
$result = rindex($str, "fo", (40 - 1)); # the value of $result is 5

1.3 Print

The syntax of 'print':
print(expression) or print expression (without parentheses; I do not like this option);
So printing scalars to the console/terminal is really easy:
$no = "one";
print("$no\n"); # prints "one"
$no_1 = "one";
$no_2 = "two";
print("$no_1\n"); # prints "one"
$no_1 = "1";
$no_2 = "2";
print($no_1, $no_2); # prints 12 (without space!)
To print the last result with a space, use a 'space' element:
$no_1 = "1";
$no_2 = "2";
print($no_1, " ", $no_2); # prints 1 2
To print strings, including variables:
$name = "Daniel";
$age = "15";
print("$name is $age years old."); # prints Daniel is 15 years old.

1.4 Iterate

The built-in function 'substr' can be used when looping (see chapter 7) through a string:
for ($i = 0; $i < length("abcdefgh"); $i++) {
print(substr("abcdefgh", $i, 2));
print("\n"); # prints ab cd ef gh on separate lines
}
One could have similar results with the 'split' function. However, some knowledge on arrays is therefore required: see chapter 4.

1.5 Operate

1.5.1 String tools

String-handling tools are an important part of a programming language. Here some tools, you've to know.
1.5.1.1 String length
print(length("abc")); # prints 3
1.5.1.2 String repetition
print("abc" x 3); # prints abcabcabc
1.5.1.3 Evaluate expressions within a string
print("2 + 2 = @{[2 + 2]}"); # prints 2 + 2 = 4
Easier -at least to remember-:
print("2 + 2 = " . (2 + 2));# print("2 + 2 = " . 2 + 2); does not work!
1.5.1.4 Reverse a string
print(scalar(reverse("abc")));
1.5.1.5 Lowercase a string
print(lc("ABC")); # prints abc; the uppercase equivalent is: uc
1.5.1.6 Uppercase a UTF8-string
use utf8;
use open qw( :std :encoding(UTF-8) );
print(uc("Čerušňa"));
1.5.1.7 Uppercase/lowercase the first character of a string
print(ucfirst("abc")); # prints Abc; the lowercase equivalent is: lcfirst
You could use nested functions.
1.5.1.8 Lowercase a string and uppercase its first character
$str = "aBCD";
print(ucfirst (lc($str))); # prints Abcd
1.5.1.9 Upper/lowercase a character in a string with \u and \l
print("Rei\unie\ur"); # prints ReiNieR
print("\lRei\lNier"); # prints reinier
1.5.1.10 Upper/lowercase a set of characters in a string with \U, \L and \E
print("r\Ueinie\Er"); # prints rEINIEr
print("R\LEINIE\ER"); # prints ReinieR
The string manipulation orchestra can be extended by regular expressions and modules (later more info on that).

1.5.2 Substring tools

Substring manipulation is also an important part of a programming language. Here some tools, you've to know.
1.5.2.1 Replace a substring
$str = "abcdefgh";
substr($str, 3, 3) = "-";
print($str); # prints abc-gh
You'll get the same result when calling substr with four arguments:
$str = "abcdefgh";
substr($str, 3, 3, "-");# 3, 3 refers to three characters from the fourth character: 'def'
print($str); # prints abc-gh
Replacing the last three characters by *:
$str = "abcdefgh";
substr($str, -3, 3, "*");
print($str); # prints abcde*
1.5.2.2 Insert a substring
To insert characters into a string, you can use 'substr' also.
$str = "abc";
print(substr($str, 0, 0, "X")); # prints Xabc
$str = "abc";
print(substr($str, 3, 0, "X")); # prints abcX
$str = "abc";
print(substr($str, 2, 0, "X")); # prints abXc
1.5.2.3 Delete a substring
To delete characters from a string, you can use 'substr' again.
$str = "abc";
print(substr($str, 0, 1, "")); # prints bc
$str = "abc";
print(substr($str, 0, 2, "")); # prints c
$str = "abc";
print(substr($str, 2, 1, "")); # prints ab
The function 'chop' removes the last character of a string.
$str = "abc";
print(chop($str)); # prints the removed character 'c'
print($str); # prints ab

1.5.3 String incrementation

You can increment strings using the ++ operator. When used with strings, the ++ operator operates similarly to its use with numeric variables (see 1b. Scalar: number, 1.5.1), but it increments the string lexicographically.
$str = "abc";
$str++;
print("Incremented string: $str\n"); # Output: Incremented string: abd
$str = "a0";
$str++;
print("Incremented string: $str\n"); # Output: Incremented string: a1
$str = "109";
$str++;
print("Incremented string: $str\n"); # Output: Incremented string: 110
The character 'z' or 'Z' deserves special attention. When the string 'Z' is incremented, the character 'Z' is incremented to 'A'. However, since this increment operation causes a wraparound (causing 'Z' to reset back to 'A'), a carry-over effect occurs. Since there is no character to the left of the character 'Z' to accommodate the carry-over, Perl adds a new character to the left of the string. So, the result becomes 'AA'.
$char = "Z";
$char++;
print("Incremented character: $char\n"); # Output: Incremented character: AA
$str = "z9";
$str++;
print("Incremented string: $str\n"); # Output: Incremented string: aa0
In the next example is 'z' preceded by 'a', so a normal carry-over can take place.
$str = "az";
$str++;
print("Incremented string: $str\n"); # Output: Incremented string: ba
Study the following code:
$str = "1a";
$str++;
print("Incremented string: $str\n"); # Output: Incremented string: 2
The string '1a' - starting with a digit and followed by a character from the class [a-zA-Z] - is interpreted as '1' according to Perl's string incrementation rules.

The string incrementation has no corresponding string decrementation.

1.6 Strings: how-to


1. How to replace multiple horizontal spaces to a single space?

A well-known question with many answers. The cleanest solution is to use the horizontal whitespace character class \h:

$data = "%     a      b           c   %";
$data =~ s/\h+/ /g;
outputs: % a b c %

\h will match tab and space from the ASCII set, non-breaking space from extended ASCII, or several Unicode characters like U+0009, U+0020 etc.

2. How to count the number of occurrences of a character/substring in a string?
$str="1bus 2bus 3 bus 4 bus";
$count = $str =~ s/bus/bus/g;
$count has the value 4

A way to compute e.g. punctuation characters:
$str="a;b;c,d:e-f-g.";
$count = $str =~ tr/,:;.-/,:;.-/;
$count has the value 7

Consider in above cases the use of an array (which I personally prefer):

$str="1bus 2bus 3 bus 4 bus";
@count_arr = $str =~ s/bus/g;
print(scalar(@count_arr)); 
Output: 4
$str="a;b;c,d:e-f-g.";
@count_arr = $str =~ /[,:;.-]+/g;
print(scalar(@count_arr)); 
Output: 7

In case of multiple character substrings, use a loop. E.g. counting negative numbers, write
$str = "1 -2 3 -5 8 13 -21 34 -53";
$count = 0;
$count++ while ($str =~ /-\d+/g);
$count has the value 4

Alternatively:
@arr = qw(1 -2 3 -5 8 13 -21 34 -53);
@arr_new = grep { $_ < 0 } @arr; 
print("@arr_new: " . scalar(@arr_new)); # output: -2 -5 -21 -53: 4

Counting and determining the positions of character i in the word 'Supercalifragilisticexpialidocious':
$str="Supercalifragilisticexpialidocious"; 
push(@arr_pos, pos($str)) while ($str =~ /i/g); 
print("Positions letter i: @arr_pos \- Number of occurrences: " . scalar(@arr_pos) . "\n");
Output: Positions of character 'i': 9 14 16 19 24 27 31 - Number of occurrences: 7


3. How to make a random string?

$str = "";
@chars = ('A'..'Z', 'a'..'z', '1'..'9', '!', '@', '#');
$str .= $chars[int(rand(@chars))] for (1 .. 8);
print("$str\n"); # Output e.g eQa#B9j7
Maybe it's more clear to write: $chars[int(rand( scalar(@chars) ))]


4. How to pad a string?
In Perl, you can use the sprintf function to pad a string. Left-padding means to be 'right-justified', e.g.:

'  reinier'
Here's an example of left-padding a string with spaces:
$original_string = "reinier";
$width = 10; # total length of the padded string
$padded_string = sprintf("%${width}s", $original_string); # %${width}s equals %10s
print "Padded String: '$padded_string'\n\n"; # Output: '   reinier'
Right-padding with a character:
$original_string = "reinier";
$padding_character = "*";
$padding_mode = "right";
($padding_mode eq "left") ? ($padding_mode = "") : ($padding_mode = "-");
$width = 10;

$padded_string = sprintf("%$padding_mode${width}s", $original_string);
$padded_string =~ s/ /$padding_character/g;

print("Padded String: '$padded_string'\n"); # Output: 'reinier***'
Center padding is rather tedious with sprintf. So, use a module like Text::Padding:
use Text::Padding;
$pad = Text::Padding->new;

$original_string = "reinier";
$padding_character = "$";
$width = 11;

$padded_string = $pad->center( $original_string, $width );
$padded_string =~ s/ /$padding_character/g;

print("Padded String: '$padded_string'\n"); # Output: '$$reinier$$'

Exit: scalar context sensitivity

If the left side (the variable being assigned a value) is a scalar variable, the right side (the values being assigned) is evaluated in scalar context. Examples of this feature will presented later: we've to look first at other data types. For now, recall 'context sensitivity' when programming Perl.