Документация
HTML CSS PHP PERL другое

Section A.8.  Answers to Chapter 9 Exercises

 
Previous
Table of Contents
Next

A.8. Answers to Chapter 9 Exercises

  1. Here's one way to do it:

        /($what){3}/
    

    Once $what has been interpolated, this gives a pattern resembling /(fred|barney){3}/. Without the parentheses, the pattern would be something like /fred|barney{3}/, which is the same as /fred|barneyyy/. So, the parentheses are required.

    Here's one way to do it:

        my $in = $ARGV[0];
        unless (defined $in) {
          die "Usage: $0 filename";
        }
        my $out = $in;
        $out =~ s/(\.\w+)?$/.out/;
        unless (open IN, "<$in") {
          die "Can't open '$in': $!";
        }
        unless (open OUT, ">$out") {
          die "Can't write '$out': $!";
        }
        while (<IN>) {
          s/Fred/Larry/gi;
          print OUT $_;
        }
    

    This program begins by naming its only command-line parameter and complaining if it didn't get it. It copies that to $out and does a substitution to change the file extension, if any, to .out. (It would be sufficient to append .out to the filename.)

    Once the filehandles IN and OUT are opened, the real program can begin. If you didn't use the /g and /i options, take off half a point since every fred and every Fred should be changed.

  2. Here's one way to do it:

        while (<IN>) {
          chomp;
          s/Fred/\n/gi;        # Replace all FREDs
          s/Wilma/Fred/gi;     # Replace all WILMAs
          s/\n/Wilma/g;        # Replace the placeholder
          print OUT "$_\n";
        }
    

    This replaces the loop from the previous program. To do this swap, we need to have some "placeholder" string that doesn't appear in the data. By using chomp (and adding the newline back for the output), we ensure that a newline (\n) can be the placeholder. (You could choose some other unlikely string as the placeholder. Another good choice would be the NUL character, \0.)

  3. Here's one way to do it:

        $^I = ".bak";          # make backups
        while (<>) {
          if (/^#!/) {         # is it the shebang line?
            $_ .= "## Copyright (C) 20XX by Yours Truly\n";
          }
        }
    

    Invoke this program with the filenames you want to update. For example, if you've been naming your exercises ex01-1, ex01-2, etc., so they all begin with ex..., you would use:

        ./fix_my_copyright ex*
    

  4. To keep from adding the copyright twice, we have to make two passes over the files. First, we make a "set" with a hash where the keys are the filenames and the values don't matter though we'll use 1 for convenience:

        my %do_these;
        foreach (@ARGV) {
          $do_these{$_} = 1;
        }
    

    Next, we'll examine the files and remove any file from our to-do list that contains the copyright. The current filename is in $ARGV, so we can use that as the hash key:

        while (<>) {
          if (/^## Copyright/) {
            delete $do_these{$ARGV};
          }
        }
    

    Finally, it's the same program as before once we've reestablished a reduced list of names in @ARGV:

        @ARGV = sort keys %do_these;
        $^I = ".bak";          # make backups
        while (<>) {
          if (/^#!/) {         # is it the shebang line?
            $_ .= "## Copyright (c) 20XX by Yours Truly\n";
          }
        }
    

    Previous
    Table of Contents
    Next
    © 2000- NIV