bluethundr has asked for the wisdom of the Perl Monks concerning the following question:

Hi guys, I have a program that I am trying to write for the llama. it is question 4 of chapter 9.

It asks the student to "Write a program to add a copyright line to all of your programs, so far by placing a line such as ' ## Copyright 200x (C) by Yours Truly.

Place it in the file immediately following the shebang line. You should edit the files "in place" and keep a backup. Presume that the programs should be invoked with the filenames on the command line.

here's my answer:
#!/usr/bin/perl use strict; use warnings; $^I = ".old"; while (<>) { if (/^#!/) { $_ .= " ## Copyright (C) 2008 Yours Truly\n"; } }
But what this code does is thankfully backup the original file, but"clobber" the contents of the file it's supposed to be editing. The output is completely blank, and I don't understand why.

Any help here would be greatly appreciated!

Replies are listed 'Best First'.
Re: clobbering output
by kyle (Abbot) on Feb 24, 2008 at 20:33 UTC

    You read and modify $_, but it doesn't print.

      I've added a print to the program, as per your suggestion. Well, it's still clobbering the output. However, now instead the output files, instead of being completely blank, have the shebang line and the copyright line, then the rest is completly obliterated. None of the text that was previously there, aside from the shebang line, are there.

      Right now, the code looks like this:
      #!/usr/bin/perl use strict; use warnings; $^I = ".old"; while (<>) { if (/^#!/) { $_ .= " ## Copyright (C) 2008 me\n"; print; } }


      I have to say, that a lot of this discussion is completely over my head. To anyone kind enough to repond, please try to bear in mind that I am working on chapter 9 in the Llama book. Thanks!
        What happens if you move the print outside of the if construct?

        CountZero

        A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

        Just to make CountZero's good suggestion more obvious, your code should probably look like this:

        #!/usr/bin/perl use strict; use warnings; $^I = ".old"; while (<>) { if (/^#!/) { $_ .= " ## Copyright (C) 2008 me\n"; } print; }

        The way you had it, the print would only happen on the line where you made the change. This way, every line is printed, whether you changed it or not.

Re: clobbering output
by CountZero (Bishop) on Feb 24, 2008 at 21:03 UTC
    perl -i"*.bak" -p -e"s/^(#!.*)/$1\n##(c)2008 by me/" change_this_file

    P.S.: I use Windows, hence the double quotes.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

      This meets the problem statement, no question.

      But I have an issue with the problem statement itself. I don't use a real shebang line. Instead, my "shebang" line is this instead:

      eval '(exit $?0)' && eval 'exec perl -w -S $0 ${1+"$@"}' && eval 'exec perl -w -S $0 $argv:q' if 0; # The above invocation finds perl in the path, wherever it may be
      So fortunately the original problem statement doesn't break it, nor does the intended solution do what it's supposed to.

      This probably isn't the place to discuss the merits of a real shebang line, but I'll mention one point anyway. My *nix home directory is automounted on countless network machines, and I don't have the time to manage $PATH on every one, etc.

      Unless there is a more elegant way than this, I'll do without a shebang.

      -QM
      --
      Quantum Mechanics: The dreams stuff is made of

Re: clobbering output
by ikegami (Patriarch) on Feb 24, 2008 at 23:59 UTC

    if (/^#!/) {
    would be more accurate as
    if ($. == 1 && /^#!/) {

      You suggest the use of $., but perlvar cautions with respect to $. that

      Because ``<>'' never does an explicit close, line numbers increase across ARGV files (but see examples under eof()).

      The OP seems to want to process multiple files from the command line. The relevant example from the entry for eof is:

      # reset line numbering on each input file while (<>) { next if /^\s*#/; # skip comments print "$.\t$_"; } continue { close ARGV if eof; # Not eof()! }
Re: clobbering output
by olus (Curate) on Feb 24, 2008 at 21:06 UTC

    You are being asked to do 'in-place' editing. Re-read the perl command switches, namelly -i. Description also available online in perlrun.

    update Thanks ysth. Didn't knew that.

Re: clobbering output
by chrism01 (Friar) on Feb 25, 2008 at 07:20 UTC
    Just to point out you are only printing out if you match the shebang line.
    You need another print to print non-matching lines...

    Cheers
    Chris

Re: clobbering output
by apl (Monsignor) on Feb 25, 2008 at 10:58 UTC
    The output is completely blank, and I don't understand why.

    What in your program is doing the output?