Workshop

The workshop provides quiz questions to help you solidify your understanding of the material covered and exercises to give you experience in using what you've learned. Try and understand the quiz and exercise answers before you go on to tomorrow's lesson.

Quiz

1:Define the terms pattern matching and regular expressions.
A1: pattern matching is the concept on Perl of writing a pattern which is then applied to a string or a set of data. Regular expressions are the language you use to write patterns.
2:What sort of tasks is pattern matching useful for? Name three.
A2: There are many uses of pattern matching—you are limited only by your imagination. A few of them include

a. Input validation

b. Counting the number of things in a string

c. Extracting data from a string based on certain criteria

d. Splitting a string into different elements

e. Replacing a specific pattern with some other string

f. Finding regular (or irregular) patterns in a data set

3:What do each of the following patterns do?
/ices*cream/
/ddd/
/^d+$/
/ab?c[,.:]d/
/xy|yz+/
/[ds]{2,3} /
/"[^"]"/

A3: The answers are as follows:

a. This pattern matches the characters “ice” and “cream,” separated by zero or more whitespace characters.

b. This pattern matches three digits in a row

c. This pattern matches one or more digits on a line by themselves with no other characters or whitespace.

d. This pattern matches 'a', and optional 'b', a c, one of a comma, period, or colon, and a 'd'. “ac.d” will match, as will “acb,d”, but not “abcd”

e. This pattern will match either 'xy' or 'y' with one or more 'z's.

f. This pattern will match either a digit or a whitespace character appearing at least two but no more than three times.

g. This pattern matches all the characters in between opening and closing quotes.

4:Assume that $_ contains the value 123 kazoo kazoo 456. What is the result of the following expressions?
if (/kaz/) {  # true or false?
while (/kaz/g) {  # what happens?
if (/^d+/) {  # true or false?
if (/^d?s/) {  # true or false?
if (/d{4} /) {  # true or false?

A4: The answers are

a. True

b. The loop repeats for every instance of 'kaz' in the string (twice, in this case).

c. True. The pattern matches one or more digits at the start of a line.

d. False. This pattern matches 0 or one digits at the start of the line, followed by whitespace. It doesn't match the three digits we have in this string.

e. False. This pattern matches four digits in a row; we only have three digits here.

Exercises

1:Write patterns to match the following things:
  • First words in a sentence (that is, words with initial capital letters following some kind of punctuation and white space)

  • Percentages (any decimals followed by a percent sign)

  • Any number (with or without a decimal point, positive or negative)

A1: As with all Perl, there are different ways of doing different things. Here are some possible solutions:
/[.!?"]s+[A-Z]w+/
/d+%/
/[+-]d+.?d+/
/([a-zA-z]{3} )s*1/

2:BUG BUSTER: What's wrong with this code?
print 'Enter a string: ';
chomp($input = <STDIN>);
print 'Search for what? ';
chomp($pat = <STDIN>);

if (/$pat/) {
   # pattern found, handle it
}

A2: There's a mismatch between where the pattern is trying to match and where the actual data is. The pattern in the if statement is trying to match the pattern against $_, but as per the second line, the actual input is in $input. Use this if test instead:
if ($input =~ /$pat/) {

3:BUG BUSTER: How about this one?
print 'Search for what? ';
chomp($pat = <STDIN>);
while (<>) {
    while (/$pat/) {
        $count++;
    }
}

A3: This one's sneaky, because there's nothing syntactically wrong with this statement. The second while loop, the one with the pattern in it, will look for the pattern in $_, which is correct. But the test is a simple true and false test: Does that pattern exist? The first line that has that pattern in it will register as true, and then $count will get incremented. But then the test will occur again, and it'll still be true, and the counter will get incremented again, and again, infinitely. There's nothing here to stop the loop from iterating.

The /g option to the pattern in that while loop is what sets up the special case where the while loop will loop only as many times as the pattern was matched in the string, and then stop. If you're using patterns inside loops, don't forget the /g.

4:Yesterday, we created a script called morenames.pl that let you sort a list of names and search for different parts. The searching part used a rather convoluted mechanism of each and grep to find the pattern. Rewrite that part of the script to use patterns instead.
A4: The only part that needs to change are the lines that build the @keys array (the ones that use grep to search for the pattern). Here we'll use a foreach loop and a test in both the key and value. We'll also add the /i option to make it not case sensitive, and also reset the @keys list to the empty list so that it doesn't build up between searches. Here's the new version of option 3:
}  elsif ($in eq '3') {      # find a name (1 or more)

   print "Search for what? ";
   chomp($search = <STDIN>);

   @keys = ();
   foreach (keys %names) {
       if (/$search/i or $names{$_}  =~ /$search/i) {
           push @keys, $_;
       }
   }

   if (@keys) {
       print "Names matched: 
";
       foreach $name (sort @keys) {
           print "   $names{$name}  $name
";
       }
   }  else {
       print "None found.
";
   }
}

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset