> # form a script
> local($^I, @ARGV) = ('.bak', glob("*.c"));
> while (<>) {
> if ($. == 1) {
> print "This line should appear at the top of each
file\n";
> }
> s/\b(p)earl\b/${1}erl/i; # Correct typos,
preserving case
> print;
> close ARGV if eof; # Reset $.
> }
A quick glance shows this is going to read through
*.c files, modifying them (and renaming the old file
to *.c.bak). In each file, it's going to stick a line at
the top and change pearl to perl.
(Both the one liner and this are clearly someone
experimenting.)
> # form a script
This isn't a complete script in a traditional sense.
Usually a perl script starts with:
#!/usr/bin/perl -w
or similar.
Anyhow:
> local($^I, @ARGV) = ('.bak', glob("*.c"));
local $foo = "bar";
local ($foo, $bar) = ("foo", "bar");
sets the variables listed on the left to the values
listed on the right. There are four ways to do this:
$foo = "foo";
my $foo = "foo";
our $foo = "foo";
local $foo = "foo";
(ok, there's lots more ways, but these are some
basics.)
our and local should refer to a global variable.
local is a form of our that tells perl to forget the
"local" value when the current {} pair is exited.
@ARGV = (1, 2);
{
local @ARGV = (3, 4);
# @ARGV contains (3, 4)...
}
# @ARGV contains (1, 2)...
In this case, the script is setting $^I and @ARGV.
$^I is the same as the -i switch at a shell prompt /
command line.
Set $^I to '' (null string) to switch inplace editing on,
without backups. Set it to a string to have backups
created with the string added to the backup name.
(You can get clever with this naming. See the doc.)
@ARGV is the list of "arguments" to the script. The
glob() takes its parameter and returns all the matching
directory entries; so in this case, @ARGV will end up
with a bunch of *.c files (presuming there are some to
match).
(When you use something like *.c at a shell prompt,
the shell does something akin to the glob() itself. So
if you do "perl -pi -e 's/foo/bar' *.c" the perl code will
operate on all the directory entries matching *.c in the
current directory.)
So, what the initial local line does is set up the rest of
the script to work on inplace editing a bunch of *.c
files, and it localizes the changes to $^I and @ARGV
just in case this bit of code is embedded in a larger
bunch of perl code that might also make use of these
variables.
> while (<>) {
A wonderful perl idiom.
This means keep grabbing lines from input, as long
as there are lines to grab. In this case, input is from
the files listed in @ARGV, one by one until all the
lines in all the files are used up, then the while quits.
The current line is stuffed into $_, the default variable
on which things like s/// and print work if not told what
variable to work on.
> if ($. == 1) {
> print "This line should appear at the top of each
file\n";
$. is the line number in the current file.
> s/\b(p)earl\b/${1}erl/i; # Correct typos,
preserving case
A pretty bizarre s/// to change pearl to perl.
\b means word boundary. Which means anywhere that
is in the middle of two characters in a string and on the
left, the character is alphanumeric (or a _) and on the
right it is not. Or vice versa. (\b also matches at the
start or end of a string.)
${foo} is the same as $foo. You usually use it if not using
it would make perl think you are talking about some other
variable than the one you mean. For example:
${foo}bar;
$foobar;
The second one is the variable $foo followed by the
literal text 'bar'.
the /i on the end of the s/// means ignore case.
> print;
Print $_ (the current line).
> close ARGV if eof; # Reset $.
Not usually needed. But in this case, the programmer
wants to reset $. (line number) as each new input file
is opened.
eof tests for end of file on the current file.
(eof() tests for end of file on the last file.)
---------------
Now, don't DARE tell me you didn't need to know
all this once you knew they were experiments... :>