home *** CD-ROM | disk | FTP | other *** search
- Subject: v15i094: Perl, release 2, Part05/15
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Larry Wall <lwall@jpl-devvax.jpl.nasa.gov>
- Posting-number: Volume 15, Issue 94
- Archive-name: perl2/part05
-
- #! /bin/sh
-
- # Make a new directory for the perl sources, cd to it, and run kits 1
- # thru 15 through sh. When all 15 kits have been run, read README.
-
- echo "This is perl 2.0 kit 5 (of 15). If kit 5 is complete, the line"
- echo '"'"End of kit 5 (of 15)"'" will echo at the end.'
- echo ""
- export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
- mkdir t 2>/dev/null
- echo Extracting perl.man.1
- sed >perl.man.1 <<'!STUFFY!FUNK!' -e 's/X//'
- X.rn '' }`
- X''' $Header: perl.man.1,v 2.0 88/06/05 00:09:23 root Exp $
- X'''
- X''' $Log: perl.man.1,v $
- X''' Revision 2.0 88/06/05 00:09:23 root
- X''' Baseline version 2.0.
- X'''
- X'''
- X.de Sh
- X.br
- X.ne 5
- X.PP
- X\fB\\$1\fR
- X.PP
- X..
- X.de Sp
- X.if t .sp .5v
- X.if n .sp
- X..
- X.de Ip
- X.br
- X.ie \\n.$>=3 .ne \\$3
- X.el .ne 3
- X.IP "\\$1" \\$2
- X..
- X'''
- X''' Set up \*(-- to give an unbreakable dash;
- X''' string Tr holds user defined translation string.
- X''' Bell System Logo is used as a dummy character.
- X'''
- X.tr \(*W-|\(bv\*(Tr
- X.ie n \{\
- X.ds -- \(*W-
- X.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
- X.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
- X.ds L" ""
- X.ds R" ""
- X.ds L' '
- X.ds R' '
- X'br\}
- X.el\{\
- X.ds -- \(em\|
- X.tr \*(Tr
- X.ds L" ``
- X.ds R" ''
- X.ds L' `
- X.ds R' '
- X'br\}
- X.TH PERL 1 LOCAL
- X.SH NAME
- Xperl - Practical Extraction and Report Language
- X.SH SYNOPSIS
- X.B perl [options] filename args
- X.SH DESCRIPTION
- X.I Perl
- Xis a interpreted language optimized for scanning arbitrary text files,
- Xextracting information from those text files, and printing reports based
- Xon that information.
- XIt's also a good language for many system management tasks.
- XThe language is intended to be practical (easy to use, efficient, complete)
- Xrather than beautiful (tiny, elegant, minimal).
- XIt combines (in the author's opinion, anyway) some of the best features of C,
- X\fIsed\fR, \fIawk\fR, and \fIsh\fR,
- Xso people familiar with those languages should have little difficulty with it.
- X(Language historians will also note some vestiges of \fIcsh\fR, Pascal, and
- Xeven BASIC-PLUS.)
- XExpression syntax corresponds quite closely to C expression syntax.
- XIf you have a problem that would ordinarily use \fIsed\fR
- Xor \fIawk\fR or \fIsh\fR, but it
- Xexceeds their capabilities or must run a little faster,
- Xand you don't want to write the silly thing in C, then
- X.I perl
- Xmay be for you.
- XThere are also translators to turn your sed and awk scripts into perl scripts.
- XOK, enough hype.
- X.PP
- XUpon startup,
- X.I perl
- Xlooks for your script in one of the following places:
- X.Ip 1. 4 2
- XSpecified line by line via
- X.B \-e
- Xswitches on the command line.
- X.Ip 2. 4 2
- XContained in the file specified by the first filename on the command line.
- X(Note that systems supporting the #! notation invoke interpreters this way.)
- X.Ip 3. 4 2
- XPassed in implicity via standard input.
- XThis only works if there are no filename arguments\*(--to pass
- Xarguments to a stdin script you must explicitly specify a - for the script name.
- X.PP
- XAfter locating your script,
- X.I perl
- Xcompiles it to an internal form.
- XIf the script is syntactically correct, it is executed.
- X.Sh "Options"
- XNote: on first reading this section may not make much sense to you. It's here
- Xat the front for easy reference.
- X.PP
- XA single-character option may be combined with the following option, if any.
- XThis is particularly useful when invoking a script using the #! construct which
- Xonly allows one argument. Example:
- X.nf
- X
- X.ne 2
- X #!/usr/bin/perl -spi.bak # same as -s -p -i.bak
- X .\|.\|.
- X
- X.fi
- XOptions include:
- X.TP 5
- X.B \-a
- Xturns on autosplit mode when used with a \-n or \-p.
- XAn implicit split command to the @F array
- Xis done as the first thing inside the implicit while loop produced by
- Xthe \-n or \-p.
- X.nf
- X
- X perl -ane 'print pop(@F),"\en";'
- X
- Xis equivalent to
- X
- X while (<>) {
- X @F = split(' ');
- X print pop(@F),"\en";
- X }
- X
- X.fi
- X.TP 5
- X.B \-D<number>
- Xsets debugging flags.
- XTo watch how it executes your script, use
- X.B \-D14.
- X(This only works if debugging is compiled into your
- X.IR perl .)
- X.TP 5
- X.B \-e commandline
- Xmay be used to enter one line of script.
- XMultiple
- X.B \-e
- Xcommands may be given to build up a multi-line script.
- XIf
- X.B \-e
- Xis given,
- X.I perl
- Xwill not look for a script filename in the argument list.
- X.TP 5
- X.B \-i<extension>
- Xspecifies that files processed by the <> construct are to be edited
- Xin-place.
- XIt does this by renaming the input file, opening the output file by the
- Xsame name, and selecting that output file as the default for print statements.
- XThe extension, if supplied, is added to the name of the
- Xold file to make a backup copy.
- XIf no extension is supplied, no backup is made.
- XSaying \*(L"perl -p -i.bak -e "s/foo/bar/;" .\|.\|. \*(R" is the same as using
- Xthe script:
- X.nf
- X
- X.ne 2
- X #!/usr/bin/perl -pi.bak
- X s/foo/bar/;
- X
- Xwhich is equivalent to
- X
- X.ne 14
- X #!/usr/bin/perl
- X while (<>) {
- X if ($ARGV ne $oldargv) {
- X rename($ARGV,$ARGV . '.bak');
- X open(ARGVOUT,">$ARGV");
- X select(ARGVOUT);
- X $oldargv = $ARGV;
- X }
- X s/foo/bar/;
- X }
- X continue {
- X print; # this prints to original filename
- X }
- X select(stdout);
- X
- X.fi
- Xexcept that the \-i form doesn't need to compare $ARGV to $oldargv to know when
- Xthe filename has changed.
- XIt does, however, use ARGVOUT for the selected filehandle.
- XNote that stdout is restored as the default output filehandle after the loop.
- X.Sp
- XYou can use eof to locate the end of each input file, in case you want
- Xto append to each file, or reset line numbering (see example under eof).
- X.TP 5
- X.B \-I<directory>
- Xmay be used in conjunction with
- X.B \-P
- Xto tell the C preprocessor where to look for include files.
- XBy default /usr/include and /usr/lib/perl are searched.
- X.TP 5
- X.B \-n
- Xcauses
- X.I perl
- Xto assume the following loop around your script, which makes it iterate
- Xover filename arguments somewhat like \*(L"sed -n\*(R" or \fIawk\fR:
- X.nf
- X
- X.ne 3
- X while (<>) {
- X .\|.\|. # your script goes here
- X }
- X
- X.fi
- XNote that the lines are not printed by default.
- XSee
- X.B \-p
- Xto have lines printed.
- XHere is an efficient way to delete all files older than a week:
- X.nf
- X
- X find . -mtime +7 -print | perl -ne 'chop;unlink;'
- X
- X.fi
- XThis is faster than using the -exec switch find because you don't have to
- Xstart a process on every filename found.
- X.TP 5
- X.B \-p
- Xcauses
- X.I perl
- Xto assume the following loop around your script, which makes it iterate
- Xover filename arguments somewhat like \fIsed\fR:
- X.nf
- X
- X.ne 5
- X while (<>) {
- X .\|.\|. # your script goes here
- X } continue {
- X print;
- X }
- X
- X.fi
- XNote that the lines are printed automatically.
- XTo suppress printing use the
- X.B \-n
- Xswitch.
- XA
- X.B \-p
- Xoverrides a
- X.B \-n
- Xswitch.
- X.TP 5
- X.B \-P
- Xcauses your script to be run through the C preprocessor before
- Xcompilation by
- X.I perl.
- X(Since both comments and cpp directives begin with the # character,
- Xyou should avoid starting comments with any words recognized
- Xby the C preprocessor such as \*(L"if\*(R", \*(L"else\*(R" or \*(L"define\*(R".)
- X.TP 5
- X.B \-s
- Xenables some rudimentary switch parsing for switches on the command line
- Xafter the script name but before any filename arguments (or before a --).
- XAny switch found there is removed from @ARGV and sets the corresponding variable in the
- X.I perl
- Xscript.
- XThe following script prints \*(L"true\*(R" if and only if the script is
- Xinvoked with a -xyz switch.
- X.nf
- X
- X.ne 2
- X #!/usr/bin/perl -s
- X if ($xyz) { print "true\en"; }
- X
- X.fi
- X.TP 5
- X.B \-S
- Xmakes perl use the PATH environment variable to search for the script
- X(unless the name of the script starts with a slash).
- XTypically this is used to emulate #! startup on machines that don't
- Xsupport #!, in the following manner:
- X.nf
- X
- X #!/usr/bin/perl
- X eval "exec /usr/bin/perl -S $0 $*"
- X if $running_under_some_shell;
- X
- X.fi
- XThe system ignores the first line and feeds the script to /bin/sh,
- Xwhich proceeds to try to execute the perl script as a shell script.
- XThe shell executes the second line as a normal shell command, and thus
- Xstarts up the perl interpreter.
- XOn some systems $0 doesn't always contain the full pathname,
- Xso the -S tells perl to search for the script if necessary.
- XAfter perl locates the script, it parses the lines and ignores them because
- Xthe variable $running_under_some_shell is never true.
- X.TP 5
- X.B \-U
- Xallows perl to do unsafe operations.
- XCurrently the only "unsafe" operation is the unlinking of directories while
- Xrunning as superuser.
- X.TP 5
- X.B \-v
- Xprints the version and patchlevel of your perl executable.
- X.TP 5
- X.B \-w
- Xprints warnings about identifiers that are mentioned only once, and scalar
- Xvariables that are used before being set.
- XAlso warns about redefined subroutines, and references to undefined
- Xsubroutines and filehandles.
- X.Sh "Data Types and Objects"
- X.PP
- XPerl has about two and a half data types: scalars, arrays of scalars, and
- Xassociative arrays.
- XScalars and arrays of scalars are first class objects, for the most part,
- Xin the sense that they can be used as a whole as values in an expression.
- XAssociative arrays can only be accessed on an association by association basis;
- Xthey don't have a value as a whole (at least not yet).
- X.PP
- XScalars are interpreted as strings or numbers as appropriate.
- XA scalar is interpreted as TRUE in the boolean sense if it is not the null
- Xstring or 0.
- XBooleans returned by operators are 1 for true and '0' or '' (the null
- Xstring) for false.
- X.PP
- XReferences to scalar variables always begin with \*(L'$\*(R', even when referring
- Xto a scalar that is part of an array.
- XThus:
- X.nf
- X
- X.ne 3
- X $days \h'|2i'# a simple scalar variable
- X $days[28] \h'|2i'# 29th element of array @days
- X $days{'Feb'}\h'|2i'# one value from an associative array
- X $#days \h'|2i'# last index of array @days
- X
- Xbut entire arrays are denoted by \*(L'@\*(R':
- X
- X @days \h'|2i'# ($days[0], $days[1],\|.\|.\|. $days[n])
- X
- X.fi
- X.PP
- XAny of these five constructs may server as an lvalue,
- Xthat is, may be assigned to.
- X(You may also use an assignment to one of these lvalues as an lvalue in
- Xcertain contexts\*(--see s, tr and chop.)
- XYou may find the length of array @days by evaluating
- X\*(L"$#days\*(R", as in
- X.IR csh .
- X(Actually, it's not the length of the array, it's the subscript of the last element, since there is (ordinarily) a 0th element.)
- XAssigning to $#days changes the length of the array.
- XShortening an array by this method does not actually destroy any values.
- XLengthening an array that was previously shortened recovers the values that
- Xwere in those elements.
- XYou can also gain some measure of efficiency by preextending an array that
- Xis going to get big.
- X(You can also extend an array by assigning to an element that is off the
- Xend of the array.
- XThis differs from assigning to $#whatever in that intervening values
- Xare set to null rather than recovered.)
- XYou can truncate an array down to nothing by assigning the null list () to
- Xit.
- XThe following are exactly equivalent
- X.nf
- X
- X @whatever = ();
- X $#whatever = $[ \- 1;
- X
- X.fi
- X.PP
- XEvery data type has its own namespace.
- XYou can, without fear of conflict, use the same name for a scalar variable,
- Xan array, an associative array, a filehandle, a subroutine name, and/or
- Xa label.
- XSince variable and array references always start with \*(L'$\*(R'
- Xor \*(L'@\*(R', the \*(L"reserved\*(R" words aren't in fact reserved
- Xwith respect to variable names.
- X(They ARE reserved with respect to labels and filehandles, however, which
- Xdon't have an initial special character.
- XHint: you could say open(LOG,'logfile') rather than open(log,'logfile').)
- XCase IS significant\*(--\*(L"FOO\*(R", \*(L"Foo\*(R" and \*(L"foo\*(R" are all
- Xdifferent names.
- XNames which start with a letter may also contain digits and underscores.
- XNames which do not start with a letter are limited to one character,
- Xe.g. \*(L"$%\*(R" or \*(L"$$\*(R".
- X(Many one character names have a predefined significance to
- X.I perl.
- XMore later.)
- X.PP
- XString literals are delimited by either single or double quotes.
- XThey work much like shell quotes:
- Xdouble-quoted string literals are subject to backslash and variable
- Xsubstitution; single-quoted strings are not.
- XThe usual backslash rules apply for making characters such as newline, tab, etc.
- XYou can also embed newlines directly in your strings, i.e. they can end on
- Xa different line than they begin.
- XThis is nice, but if you forget your trailing quote, the error will not be
- Xreported until perl finds another line containing the quote character, which
- Xmay be much further on in the script.
- XVariable substitution inside strings is limited (currently) to simple scalar variables.
- XThe following code segment prints out \*(L"The price is $100.\*(R"
- X.nf
- X
- X.ne 2
- X $Price = '$100';\h'|3.5i'# not interpreted
- X print "The price is $Price.\e\|n";\h'|3.5i'# interpreted
- X
- X.fi
- XNote that you can put curly brackets around the identifier to delimit it
- Xfrom following alphanumerics.
- X.PP
- XArray literals are denoted by separating individual values by commas, and
- Xenclosing the list in parentheses.
- XIn a context not requiring an array value, the value of the array literal
- Xis the value of the final element, as in the C comma operator.
- XFor example,
- X.nf
- X
- X.ne 4
- X @foo = ('cc', '\-E', $bar);
- X
- Xassigns the entire array value to array foo, but
- X
- X $foo = ('cc', '\-E', $bar);
- X
- X.fi
- Xassigns the value of variable bar to variable foo.
- XArray lists may be assigned to if and only if each element of the list
- Xis an lvalue:
- X.nf
- X
- X ($a, $b, $c) = (1, 2, 3);
- X
- X ($map{'red'}, $map{'blue'}, $map{'green'}) = (0x00f, 0x0f0, 0xf00);
- X
- X.fi
- XArray assignment returns the number of elements assigned.
- X.PP
- XNumeric literals are specified in any of the usual floating point or
- Xinteger formats.
- X.PP
- XThere are several other pseudo-literals that you should know about.
- XIf a string is enclosed by backticks (grave accents), it first undergoes
- Xvariable substitution just like a double quoted string.
- XIt is then interpreted as a command, and the output of that command
- Xis the value of the pseudo-literal, like in a shell.
- XThe command is executed each time the pseudo-literal is evaluated.
- XThe status value of the command is returned in $? (see Predefined Names
- Xfor the interpretation of $?).
- XUnlike in \f2csh\f1, no translation is done on the return
- Xdata\*(--newlines remain newlines.
- XUnlike in any of the shells, single quotes do not hide variable names
- Xin the command from interpretation.
- XTo pass a $ through to the shell you need to hide it with a backslash.
- X.PP
- XEvaluating a filehandle in angle brackets yields the next line
- Xfrom that file (newline included, so it's never false until EOF).
- XOrdinarily you must assign that value to a variable,
- Xbut there is one situation where in which an automatic assignment happens.
- XIf (and only if) the input symbol is the only thing inside the conditional of a
- X.I while
- Xloop, the value is
- Xautomatically assigned to the variable \*(L"$_\*(R".
- X(This may seem like an odd thing to you, but you'll use the construct
- Xin almost every
- X.I perl
- Xscript you write.)
- XAnyway, the following lines are equivalent to each other:
- X.nf
- X
- X.ne 3
- X while ($_ = <stdin>) {
- X while (<stdin>) {
- X for (\|;\|<stdin>;\|) {
- X
- X.fi
- XThe filehandles
- X.IR stdin ,
- X.I stdout
- Xand
- X.I stderr
- Xare predefined.
- XAdditional filehandles may be created with the
- X.I open
- Xfunction.
- X.PP
- XIf a <FILEHANDLE> is used in a context that is looking for an array, an array
- Xconsisting of all the input lines is returned, one line per array element.
- XIt's easy to make a LARGE data space this way, so use with care.
- X.PP
- XThe null filehandle <> is special and can be used to emulate the behavior of
- X\fIsed\fR and \fIawk\fR.
- XInput from <> comes either from standard input, or from each file listed on
- Xthe command line.
- XHere's how it works: the first time <> is evaluated, the ARGV array is checked,
- Xand if it is null, $ARGV[0] is set to '-', which when opened gives you standard
- Xinput.
- XThe ARGV array is then processed as a list of filenames.
- XThe loop
- X.nf
- X
- X.ne 3
- X while (<>) {
- X .\|.\|. # code for each line
- X }
- X
- X.ne 10
- Xis equivalent to
- X
- X unshift(@ARGV, '\-') \|if \|$#ARGV < $[;
- X while ($ARGV = shift) {
- X open(ARGV, $ARGV);
- X while (<ARGV>) {
- X .\|.\|. # code for each line
- X }
- X }
- X
- X.fi
- Xexcept that it isn't as cumbersome to say.
- XIt really does shift array ARGV and put the current filename into
- Xvariable ARGV.
- XIt also uses filehandle ARGV internally.
- XYou can modify @ARGV before the first <> as long as you leave the first
- Xfilename at the beginning of the array.
- XLine numbers ($.) continue as if the input was one big happy file.
- X(But see example under eof for how to reset line numbers on each file.)
- X.PP
- X.ne 5
- XIf you want to set @ARGV to your own list of files, go right ahead.
- XIf you want to pass switches into your script, you can
- Xput a loop on the front like this:
- X.nf
- X
- X.ne 10
- X while ($_ = $ARGV[0], /\|^\-/\|) {
- X shift;
- X last if /\|^\-\|\-$\|/\|;
- X /\|^\-D\|(.*\|)/ \|&& \|($debug = $1);
- X /\|^\-v\|/ \|&& \|$verbose++;
- X .\|.\|. # other switches
- X }
- X while (<>) {
- X .\|.\|. # code for each line
- X }
- X
- X.fi
- XThe <> symbol will return FALSE only once.
- XIf you call it again after this it will assume you are processing another
- X@ARGV list, and if you haven't set @ARGV, will input from stdin.
- X.PP
- XIf the string inside the angle brackets is a reference to a scalar variable
- X(e.g. <$foo>),
- Xthen that variable contains the name of the filehandle to input from.
- X.PP
- XIf the string inside angle brackets is not a filehandle, it is interpreted
- Xas a filename pattern to be globbed, and either an array of filenames or the
- Xnext filename in the list is returned, depending on context.
- XOne level of $ interpretation is done first, but you can't say <$foo>
- Xbecause that's an indirect filehandle as explained in the previous
- Xparagraph.
- XYou could insert curly brackets to force interpretation as a
- Xfilename glob: <${foo}>.
- XExample:
- X.nf
- X
- X.ne 3
- X while (<*.c>) {
- X chmod 0644,$_;
- X }
- X
- Xis equivalent to
- X
- X.ne 5
- X open(foo,"echo *.c | tr -s ' \et\er\ef' '\e\e012\e\e012\e\e012\e\e012'|");
- X while (<foo>) {
- X chop;
- X chmod 0644,$_;
- X }
- X
- X.fi
- XIn fact, it's currently implemented that way.
- X(Which means it will not work on filenames with spaces in them.)
- XOf course, the shortest way to do the above is:
- X.nf
- X
- X chmod 0644,<*.c>;
- X
- X.fi
- X.Sh "Syntax"
- X.PP
- XA
- X.I perl
- Xscript consists of a sequence of declarations and commands.
- XThe only things that need to be declared in
- X.I perl
- Xare report formats and subroutines.
- XSee the sections below for more information on those declarations.
- XAll objects are assumed to start with a null or 0 value.
- XThe sequence of commands is executed just once, unlike in
- X.I sed
- Xand
- X.I awk
- Xscripts, where the sequence of commands is executed for each input line.
- XWhile this means that you must explicitly loop over the lines of your input file
- X(or files), it also means you have much more control over which files and which
- Xlines you look at.
- X(Actually, I'm lying\*(--it is possible to do an implicit loop with either the
- X.B \-n
- Xor
- X.B \-p
- Xswitch.)
- X.PP
- XA declaration can be put anywhere a command can, but has no effect on the
- Xexecution of the primary sequence of commands.
- XTypically all the declarations are put at the beginning or the end of the script.
- X.PP
- X.I Perl
- Xis, for the most part, a free-form language.
- X(The only exception to this is format declarations, for fairly obvious reasons.)
- XComments are indicated by the # character, and extend to the end of the line.
- XIf you attempt to use /* */ C comments, it will be interpreted either as
- Xdivision or pattern matching, depending on the context.
- XSo don't do that.
- X.Sh "Compound statements"
- XIn
- X.IR perl ,
- Xa sequence of commands may be treated as one command by enclosing it
- Xin curly brackets.
- XWe will call this a BLOCK.
- X.PP
- XThe following compound commands may be used to control flow:
- X.nf
- X
- X.ne 4
- X if (EXPR) BLOCK
- X if (EXPR) BLOCK else BLOCK
- X if (EXPR) BLOCK elsif (EXPR) BLOCK .\|.\|. else BLOCK
- X LABEL while (EXPR) BLOCK
- X LABEL while (EXPR) BLOCK continue BLOCK
- X LABEL for (EXPR; EXPR; EXPR) BLOCK
- X LABEL foreach VAR (ARRAY) BLOCK
- X LABEL BLOCK continue BLOCK
- X
- X.fi
- XNote that, unlike C and Pascal, these are defined in terms of BLOCKs, not
- Xstatements.
- XThis means that the curly brackets are \fIrequired\fR\*(--no dangling statements allowed.
- XIf you want to write conditionals without curly brackets there are several
- Xother ways to do it.
- XThe following all do the same thing:
- X.nf
- X
- X.ne 5
- X if (!open(foo)) { die "Can't open $foo"; }
- X die "Can't open $foo" unless open(foo);
- X open(foo) || die "Can't open $foo"; # foo or bust!
- X open(foo) ? die "Can't open $foo" : 'hi mom';
- X # a bit exotic, that last one
- X
- X.fi
- X.PP
- XThe
- X.I if
- Xstatement is straightforward.
- XSince BLOCKs are always bounded by curly brackets, there is never any
- Xambiguity about which
- X.I if
- Xan
- X.I else
- Xgoes with.
- XIf you use
- X.I unless
- Xin place of
- X.IR if ,
- Xthe sense of the test is reversed.
- X.PP
- XThe
- X.I while
- Xstatement executes the block as long as the expression is true
- X(does not evaluate to the null string or 0).
- XThe LABEL is optional, and if present, consists of an identifier followed by
- Xa colon.
- XThe LABEL identifies the loop for the loop control statements
- X.IR next ,
- X.I last
- Xand
- X.I redo
- X(see below).
- XIf there is a
- X.I continue
- XBLOCK, it is always executed just before
- Xthe conditional is about to be evaluated again, similarly to the third part
- Xof a
- X.I for
- Xloop in C.
- XThus it can be used to increment a loop variable, even when the loop has
- Xbeen continued via the
- X.I next
- Xstatement (similar to the C \*(L"continue\*(R" statement).
- X.PP
- XIf the word
- X.I while
- Xis replaced by the word
- X.IR until ,
- Xthe sense of the test is reversed, but the conditional is still tested before
- Xthe first iteration.
- X.PP
- XIn either the
- X.I if
- Xor the
- X.I while
- Xstatement, you may replace \*(L"(EXPR)\*(R" with a BLOCK, and the conditional
- Xis true if the value of the last command in that block is true.
- X.PP
- XThe
- X.I for
- Xloop works exactly like the corresponding
- X.I while
- Xloop:
- X.nf
- X
- X.ne 12
- X for ($i = 1; $i < 10; $i++) {
- X .\|.\|.
- X }
- X
- Xis the same as
- X
- X $i = 1;
- X while ($i < 10) {
- X .\|.\|.
- X } continue {
- X $i++;
- X }
- X.fi
- X.PP
- XThe foreach loop iterates over a normal array value and sets the variable
- XVAR to be each element of the array in turn.
- XThe "foreach" keyword is actually identical to the "for" keyword,
- Xso you can use "foreach" for readability or "for" for brevity.
- XIf VAR is omitted, $_ is set to each value.
- XIf ARRAY is an actual array (as opposed to an expression returning an array
- Xvalue), you can modify each element of the array
- Xby modifying VAR inside the loop.
- XExamples:
- X.nf
- X
- X.ne 5
- X for (@ary) { s/foo/bar/; }
- X
- X foreach $elem (@elements) {
- X $elem *= 2;
- X }
- X
- X for ((10,9,8,7,6,5,4,3,2,1,'BOOM')) {
- X print $_,"\en"; sleep(1);
- X }
- X
- X.ne 3
- X foreach $item (split(/:[\e\e\en:]*/,$ENV{'TERMCAP'}) {
- X print "Item: $item\en";
- X }
- X.fi
- X.PP
- XThe BLOCK by itself (labeled or not) is equivalent to a loop that executes
- Xonce.
- XThus you can use any of the loop control statements in it to leave or
- Xrestart the block.
- XThe
- X.I continue
- Xblock is optional.
- XThis construct is particularly nice for doing case structures.
- X.nf
- X
- X.ne 6
- X foo: {
- X if (/abc/) { $abc = 1; last foo; }
- X if (/def/) { $def = 1; last foo; }
- X if (/xyz/) { $xyz = 1; last foo; }
- X $nothing = 1;
- X }
- X
- X.fi
- XIt's also nice for exiting subroutines early.
- XNote the double curly brackets:
- X.nf
- X
- X.ne 8
- X sub tokenize {{
- X .\|.\|.
- X if (/foo/) {
- X 23; # return value
- X last;
- X }
- X .\|.\|.
- X }}
- X
- X.fi
- X.Sh "Simple statements"
- XThe only kind of simple statement is an expression evaluated for its side
- Xeffects.
- XEvery expression (simple statement) must be terminated with a semicolon.
- XNote that this is like C, but unlike Pascal (and
- X.IR awk ).
- X.PP
- XAny simple statement may optionally be followed by a
- Xsingle modifier, just before the terminating semicolon.
- XThe possible modifiers are:
- X.nf
- X
- X.ne 4
- X if EXPR
- X unless EXPR
- X while EXPR
- X until EXPR
- X
- X.fi
- XThe
- X.I if
- Xand
- X.I unless
- Xmodifiers have the expected semantics.
- XThe
- X.I while
- Xand
- X.I until
- Xmodifiers also have the expected semantics (conditional evaluated first),
- Xexcept when applied to a do-BLOCK command,
- Xin which case the block executes once before the conditional is evaluated.
- XThis is so that you can write loops like:
- X.nf
- X
- X.ne 4
- X do {
- X $_ = <stdin>;
- X .\|.\|.
- X } until $_ \|eq \|".\|\e\|n";
- X
- X.fi
- X(See the
- X.I do
- Xoperator below. Note also that the loop control commands described later will
- XNOT work in this construct, since modifiers don't take loop labels.
- XSorry.)
- X.Sh "Expressions"
- XSince
- X.I perl
- Xexpressions work almost exactly like C expressions, only the differences
- Xwill be mentioned here.
- X.PP
- XHere's what
- X.I perl
- Xhas that C doesn't:
- X.Ip (\|) 8 3
- XThe null list, used to initialize an array to null.
- X.Ip . 8
- XConcatenation of two strings.
- X.Ip .= 8
- XThe corresponding assignment operator.
- X.Ip eq 8
- XString equality (== is numeric equality).
- XFor a mnemonic just think of \*(L"eq\*(R" as a string.
- X(If you are used to the
- X.I awk
- Xbehavior of using == for either string or numeric equality
- Xbased on the current form of the comparands, beware!
- XYou must be explicit here.)
- X.Ip ne 8
- XString inequality (!= is numeric inequality).
- X.Ip lt 8
- XString less than.
- X.Ip gt 8
- XString greater than.
- X.Ip le 8
- XString less than or equal.
- X.Ip ge 8
- XString greater than or equal.
- X.Ip =~ 8 2
- XCertain operations search or modify the string \*(L"$_\*(R" by default.
- XThis operator makes that kind of operation work on some other string.
- XThe right argument is a search pattern, substitution, or translation.
- XThe left argument is what is supposed to be searched, substituted, or
- Xtranslated instead of the default \*(L"$_\*(R".
- XThe return value indicates the success of the operation.
- X(If the right argument is an expression other than a search pattern,
- Xsubstitution, or translation, it is interpreted as a search pattern
- Xat run time.
- XThis is less efficient than an explicit search, since the pattern must
- Xbe compiled every time the expression is evaluated.)
- XThe precedence of this operator is lower than unary minus and autoincrement/decrement, but higher than everything else.
- X.Ip !~ 8
- XJust like =~ except the return value is negated.
- X.Ip x 8
- XThe repetition operator.
- XReturns a string consisting of the left operand repeated the
- Xnumber of times specified by the right operand.
- X.nf
- X
- X print '-' x 80; # print row of dashes
- X print '-' x80; # illegal, x80 is identifier
- X
- X print "\et" x ($tab/8), ' ' x ($tab%8); # tab over
- X
- X.fi
- X.Ip x= 8
- XThe corresponding assignment operator.
- X.Ip .. 8
- XThe range operator, which is bistable.
- XEach .. operator maintains its own boolean state.
- XIt is false as long as its left operand is false.
- XOnce the left operand is true, the range operator stays true
- Xuntil the right operand is true,
- XAFTER which the range operator becomes false again.
- X(It doesn't become false till the next time the range operator evaluated.
- XIt can become false on the same evaluation it became true, but it still returns
- Xtrue once.)
- XThe right operand is not evaluated while the operator is in the "false" state,
- Xand the left operand is not evaluated while the operator is in the "true" state.
- XThe .. operator is primarily intended for doing line number ranges after
- Xthe fashion of \fIsed\fR or \fIawk\fR.
- XThe precedence is a little lower than || and &&.
- XThe value returned is either the null string for false, or a sequence number
- X(beginning with 1) for true.
- XThe sequence number is reset for each range encountered.
- XThe final sequence number in a range has the string 'E0' appended to it, which
- Xdoesn't affect its numeric value, but gives you something to search for if you
- Xwant to exclude the endpoint.
- XYou can exclude the beginning point by waiting for the sequence number to be
- Xgreater than 1.
- XIf either operand of .. is static, that operand is implicitly compared to
- Xthe $. variable, the current line number.
- XExamples:
- X.nf
- X
- X.ne 5
- X if (101 .. 200) { print; } # print 2nd hundred lines
- X
- X next line if (1 .. /^$/); # skip header lines
- X
- X s/^/> / if (/^$/ .. eof()); # quote body
- X
- X.fi
- X.Ip \-x 8
- XA file test.
- XThis unary operator takes one argument, either a filename or a filehandle,
- Xand tests the associated file to see if something is true about it.
- XIf the argument is omitted, tests $_, except for \-t, which tests stdin.
- XIt returns 1 for true and '' for false.
- XPrecedence is higher than logical and relational operators, but lower than
- Xarithmetic operators.
- XThe operator may be any of:
- X.nf
- X \-r File is readable by effective uid.
- X \-w File is writeable by effective uid.
- X \-x File is executable by effective uid.
- X \-o File is owned by effective uid.
- X \-R File is readable by real uid.
- X \-W File is writeable by real uid.
- X \-X File is executable by real uid.
- X \-O File is owned by real uid.
- X \-e File exists.
- X \-z File has zero size.
- X \-s File has non-zero size.
- X \-f File is a plain file.
- X \-d File is a directory.
- X \-l File is a symbolic link.
- X \-p File is a named pipe (FIFO).
- X \-S File is a socket.
- X \-b File is a block special file.
- X \-c File is a character special file.
- X \-u File has setuid bit set.
- X \-g File has setgid bit set.
- X \-k File has sticky bit set.
- X \-t Filehandle is opened to a tty.
- X \-T File is a text file.
- X \-B File is a binary file (opposite of \-T).
- X
- X.fi
- XThe interpretation of the file permission operators \-r, \-R, \-w, \-W, \-x and \-X
- Xis based solely on the mode of the file and the uids and gids of the user.
- XThere may be other reasons you can't actually read, write or execute the file.
- XAlso note that, for the superuser, \-r, \-R, \-w and \-W always return 1, and
- X\-x and \-X return 1 if any execute bit is set in the mode.
- XScripts run by the superuser may thus need to do a stat() in order to determine
- Xthe actual mode of the file, or temporarily set the uid to something else.
- X.Sp
- XExample:
- X.nf
- X.ne 7
- X
- X while (<>) {
- X chop;
- X next unless \-f $_; # ignore specials
- X .\|.\|.
- X }
- X
- X.fi
- XNote that -s/a/b/ does not do a negated substitution.
- XSaying -exp($foo) still works as expected, however\*(--only single letters
- Xfollowing a minus are interpreted as file tests.
- X.Sp
- XThe \-T and \-B switches work as follows.
- XThe first block or so of the file is examined for odd characters such as
- Xstrange control codes or metacharacters.
- XIf too many odd characters (>10%) are found, it's a \-B file, otherwise it's a \-T file.
- XAlso, any file containing null in the first block is considered a binary file.
- XIf \-T or \-B is used on a filehandle, the current stdio buffer is examined
- Xrather than the first block.
- XSince input doesn't work well on binary files you should probably test a
- Xfilehandle before doing any input if you're unsure of the nature of the
- Xfilehandle you've been handed (usually via stdin).
- XBoth \-T and \-B return TRUE on a null file, or a file at EOF when testing
- Xa filehandle.
- X.PP
- XHere is what C has that
- X.I perl
- Xdoesn't:
- X.Ip "unary &" 12
- XAddress-of operator.
- X.Ip "unary *" 12
- XDereference-address operator.
- X.Ip "(TYPE)" 12
- XType casting operator.
- X.PP
- XLike C,
- X.I perl
- Xdoes a certain amount of expression evaluation at compile time, whenever
- Xit determines that all of the arguments to an operator are static and have
- Xno side effects.
- XIn particular, string concatenation happens at compile time between literals that don't do variable substitution.
- XBackslash interpretation also happens at compile time.
- XYou can say
- X.nf
- X
- X.ne 2
- X 'Now is the time for all' . "\|\e\|n" .
- X 'good men to come to.'
- X
- X.fi
- Xand this all reduces to one string internally.
- X.PP
- XThe autoincrement operator has a little extra built-in magic to it.
- XIf you increment a variable that is numeric, or that has ever been used in
- Xa numeric context, you get a normal increment.
- XIf, however, the variable has only been used in string contexts since it
- Xwas set, and has a value that is not null and matches the
- Xpattern /^[a-zA-Z]*[0-9]*$/, the increment is done
- Xas a string, preserving each character within its range, with carry:
- X.nf
- X
- X print ++($foo = '99'); # prints '100'
- X print ++($foo = 'a0'); # prints 'a1'
- X print ++($foo = 'Az'); # prints 'Ba'
- X print ++($foo = 'zz'); # prints 'aaa'
- X
- X.fi
- XThe autodecrement is not magical.
- X.PP
- XAlong with the literals and variables mentioned earlier,
- Xthe following operations can serve as terms in an expression.
- XSome of these operations take a LIST as an argument.
- XSuch a list can consist of any combination of scalar arguments or arrays;
- Xthe arrays will be included in the list as if each individual element were
- Xinterpolated at that point in the list.
- X.Ip "/PATTERN/i" 8 4
- XSearches a string for a pattern, and returns true (1) or false ('').
- XIf no string is specified via the =~ or !~ operator,
- Xthe $_ string is searched.
- X(The string specified with =~ need not be an lvalue\*(--it may be the result of an expression evaluation, but remember the =~ binds rather tightly.)
- XSee also the section on regular expressions.
- X.Sp
- XIf you prepend an `m' you can use any pair of characters as delimiters.
- XThis is particularly useful for matching Unix path names that contain `/'.
- XIf the final delimiter is followed by the optional letter `i', the matching is
- Xdone in a case-insensitive manner.
- X.Sp
- XIf used in a context that requires an array value, a pattern match returns an
- Xarray consisting of the subexpressions matched by the parens in pattern,
- Xi.e. ($1, $2, $3.\|.\|.).
- X.Sp
- XExamples:
- X.nf
- X
- X.ne 4
- X open(tty, '/dev/tty');
- X <tty> \|=~ \|/\|^y\|/i \|&& \|do foo(\|); # do foo if desired
- X
- X if (/Version: \|*\|([0-9.]*\|)\|/\|) { $version = $1; }
- X
- X next if m#^/usr/spool/uucp#;
- X
- X if (($F1,$F2,$Etc) = ($foo =~ /^(\eS+)\es+(\eS+)\es*(.*)/))
- X
- X.fi
- XThis last example splits $foo into the first two words and the remainder
- Xof the line, and assigns those three fields to $F1, $F2 and $Etc.
- XThe conditional is true if any variables were assigned, i.e. if the pattern
- Xmatched.
- X.Ip "?PATTERN?" 8 4
- XThis is just like the /pattern/ search, except that it matches only once between
- Xcalls to the
- X.I reset
- Xoperator.
- XThis is a useful optimization when you only want to see the first occurence of
- Xsomething in each file of a set of files, for instance.
- X.Ip "chdir EXPR" 8 2
- XChanges the working directory to EXPR, if possible.
- XReturns 1 upon success, 0 otherwise.
- XSee example under die().
- X.Ip "chmod LIST" 8 2
- XChanges the permissions of a list of files.
- XThe first element of the list must be the numerical mode.
- XReturns the number of files successfully changed.
- X.nf
- X
- X.ne 2
- X $cnt = chmod 0755,'foo','bar';
- X chmod 0755,@executables;
- X
- X.fi
- X.Ip "chop(VARIABLE)" 8 5
- X.Ip "chop" 8
- XChops off the last character of a string and returns it.
- XIt's used primarily to remove the newline from the end of an input record,
- Xbut is much more efficient than s/\en// because it neither scans nor copies
- Xthe string.
- XIf VARIABLE is omitted, chops $_.
- XExample:
- X.nf
- X
- X.ne 5
- X while (<>) {
- X chop; # avoid \en on last field
- X @array = split(/:/);
- X .\|.\|.
- X }
- X
- X.fi
- XYou can actually chop anything that's an lvalue, including an assignment:
- X.nf
- X
- X chop($cwd = `pwd`);
- X
- X.fi
- X.Ip "chown LIST" 8 2
- XChanges the owner (and group) of a list of files.
- XThe first two elements of the list must be the NUMERICAL uid and gid,
- Xin that order.
- XReturns the number of files successfully changed.
- X.nf
- X
- X.ne 2
- X $cnt = chown $uid,$gid,'foo','bar';
- X chown $uid,$gid,@filenames;
- X
- X.fi
- X.ne 23
- XHere's an example of looking up non-numeric uids:
- X.nf
- X
- X print "User: ";
- X $user = <stdin>;
- X chop($user);
- X print "Files: "
- X $pattern = <stdin>;
- X chop($pattern);
- X open(pass,'/etc/passwd') || die "Can't open passwd";
- X while (<pass>) {
- X ($login,$pass,$uid,$gid) = split(/:/);
- X $uid{$login} = $uid;
- X $gid{$login} = $gid;
- X }
- X @ary = <$pattern>; # get filenames
- X if ($uid{$user} eq '') {
- X die "$user not in passwd file";
- X }
- X else {
- X unshift(@ary,$uid{$user},$gid{$user});
- X chown @ary;
- X }
- X
- X.fi
- X.Ip "close(FILEHANDLE)" 8 5
- X.Ip "close FILEHANDLE" 8
- XCloses the file or pipe associated with the file handle.
- XYou don't have to close FILEHANDLE if you are immediately going to
- Xdo another open on it, since open will close it for you.
- X(See
- X.IR open .)
- XHowever, an explicit close on an input file resets the line counter ($.), while
- Xthe implicit close done by
- X.I open
- Xdoes not.
- XAlso, closing a pipe will wait for the process executing on the pipe to complete,
- Xin case you want to look at the output of the pipe afterwards.
- XExample:
- X.nf
- X
- X.ne 4
- X open(output,'|sort >foo'); # pipe to sort
- X .\|.\|. # print stuff to output
- X close(output); # wait for sort to finish
- X open(input,'foo'); # get sort's results
- X
- X.fi
- XFILEHANDLE may be an expression whose value gives the real filehandle name.
- X.Ip "crypt(PLAINTEXT,SALT)" 8 6
- XEncrypts a string exactly like the crypt() function in the C library.
- XUseful for checking the password file for lousy passwords.
- XOnly the guys wearing white hats should do this.
- X.Ip "delete $ASSOC{KEY}" 8 6
- XDeletes the specified value from the specified associative array.
- XReturns the deleted value;
- XThe following deletes all the values of an associative array:
- X.nf
- X
- X.ne 3
- X foreach $key (keys(ARRAY)) {
- X delete $ARRAY{$key};
- X }
- X
- X.fi
- X(But it would be faster to use the reset command.)
- X.Ip "die EXPR" 8 6
- XPrints the value of EXPR to stderr and exits with the current value of $!
- X(errno).
- XIf $! is 0, exits with the value of ($? >> 8) (`command` status).
- XIf ($? >> 8) is 0, exits with 255.
- XEquivalent examples:
- X.nf
- X
- X.ne 3
- X die "Can't cd to spool.\en" unless chdir '/usr/spool/news';
- X
- X chdir '/usr/spool/news' || die "Can't cd to spool.\en"
- X
- X.fi
- X.Sp
- XIf the value of EXPR does not end in a newline, the current script line
- Xnumber and input line number (if any) are also printed, and a newline is
- Xsupplied.
- XHint: sometimes appending ", stopped" to your message will cause it to make
- Xbetter sense when the string "at foo line 123" is appended.
- XSuppose you are running script "canasta".
- X.nf
- X
- X.ne 7
- X die "/etc/games is no good";
- X die "/etc/games is no good, stopped";
- X
- Xproduce, respectively
- X
- X /etc/games is no good at canasta line 123.
- X /etc/games is no good, stopped at canasta line 123.
- X
- X.fi
- XSee also
- X.IR exit .
- X.Ip "do BLOCK" 8 4
- XReturns the value of the last command in the sequence of commands indicated
- Xby BLOCK.
- XWhen modified by a loop modifier, executes the BLOCK once before testing the
- Xloop condition.
- X(On other statements the loop modifiers test the conditional first.)
- X.Ip "do SUBROUTINE (LIST)" 8 3
- XExecutes a SUBROUTINE declared by a
- X.I sub
- Xdeclaration, and returns the value
- Xof the last expression evaluated in SUBROUTINE.
- XIf you pass arrays as part of LIST you may wish to pass the length
- Xof the array in front of each array.
- X(See the section on subroutines later on.)
- XSUBROUTINE may be a scalar variable, in which case the variable contains
- Xthe name of the subroutine to execute.
- XThe parentheses are required to avoid confusion with the next form of "do".
- X.Ip "do EXPR" 8 3
- XUses the value of EXPR as a filename and executes the contents of the file
- Xas a perl script.
- XIt's primary use is to include subroutines from a perl subroutine library.
- X.nf
- X do 'stat.pl';
- X
- Xis just like
- X
- X eval `cat stat.pl`;
- X
- X.fi
- Xexcept that it's more efficient, more concise, keeps track of the current
- Xfilename for error messages, and searches all the -I libraries if the file
- Xisn't in the current directory (see also the @INC array in Predefined Names).
- XIt's the same, however, in that it does reparse the file every time you
- Xcall it, so if you are going to use the file inside a loop you might prefer
- Xto use #include, at the expense of a little more startup time.
- X(The main problem with #include is that cpp doesn't grok # comments--a
- Xworkaround is to use ";#" for standalone comments.)
- XNote that the following are NOT equivalent:
- X.nf
- X
- X.ne 2
- X do $foo; # eval a file
- X do $foo(); # call a subroutine
- X
- X.fi
- X.Ip "each(ASSOC_ARRAY)" 8 6
- XReturns a 2 element array consisting of the key and value for the next
- Xvalue of an associative array, so that you can iterate over it.
- XEntries are returned in an apparently random order.
- XWhen the array is entirely read, a null array is returned (which when
- Xassigned produces a FALSE (0) value).
- XThe next call to each() after that will start iterating again.
- XThe iterator can be reset only by reading all the elements from the array.
- XYou must not modify the array while iterating over it.
- XThere is a single iterator for each associative array, shared by all
- Xeach(), keys() and values() function calls in the program.
- XThe following prints out your environment like the printenv program, only
- Xin a different order:
- X.nf
- X
- X.ne 3
- X while (($key,$value) = each(ENV)) {
- X print "$key=$value\en";
- X }
- X
- X.fi
- XSee also keys() and values().
- X.Ip "eof(FILEHANDLE)" 8 8
- X.Ip "eof" 8
- XReturns 1 if the next read on FILEHANDLE will return end of file, or if
- XFILEHANDLE is not open.
- XFILEHANDLE may be an expression whose value gives the real filehandle name.
- XAn eof without an argument returns the eof status for the last file read.
- XEmpty parentheses () may be used to indicate the pseudo file formed of the
- Xfiles listed on the command line, i.e. eof() is reasonable to use inside
- Xa while (<>) loop to detect the end of only the last file.
- XUse eof(ARGV) or eof without the parens to test EACH file in a while (<>) loop.
- XExamples:
- X.nf
- X
- X.ne 7
- X # insert dashes just before last line of last file
- X while (<>) {
- X if (eof()) {
- X print "--------------\en";
- X }
- X print;
- X }
- X
- X.ne 7
- X # reset line numbering on each input file
- X while (<>) {
- X print "$.\et$_";
- X if (eof) { # Not eof().
- X close(ARGV);
- X }
- X }
- X
- X.fi
- X.Ip "eval EXPR" 8 6
- XEXPR is parsed and executed as if it were a little perl program.
- XIt is executed in the context of the current perl program, so that
- Xany variable settings, subroutine or format definitions remain afterwards.
- XThe value returned is the value of the last expression evaluated, just
- Xas with subroutines.
- XIf there is a syntax error or runtime error, a null string is returned by
- Xeval, and $@ is set to the error message.
- XIf there was no error, $@ is null.
- XIf EXPR is omitted, evaluates $_.
- X.Ip "exec LIST" 8 6
- XIf there is more than one argument in LIST,
- Xcalls execvp() with the arguments in LIST.
- XIf there is only one argument, the argument is checked for shell metacharacters.
- XIf there are any, the entire argument is passed to /bin/sh -c for parsing.
- XIf there are none, the argument is split into words and passed directly to
- Xexecvp(), which is more efficient.
- XNote: exec (and system) do not flush your output buffer, so you may need to
- Xset $| to avoid lost output.
- XExamples:
- X.nf
- X
- X exec '/bin/echo', 'Your arguments are: ', @ARGV;
- X exec "sort $outfile | uniq";
- X
- X.fi
- X.Ip "exit EXPR" 8 6
- XEvaluates EXPR and exits immediately with that value.
- XExample:
- X.nf
- X
- X.ne 2
- X $ans = <stdin>;
- X exit 0 \|if \|$ans \|=~ \|/\|^[Xx]\|/\|;
- X
- X.fi
- XSee also
- X.IR die .
- X.Ip "exp(EXPR)" 8 3
- XReturns e to the power of EXPR.
- X.Ip "fork" 8 4
- XDoes a fork() call.
- XReturns the child pid to the parent process and 0 to the child process.
- XNote: unflushed buffers remain unflushed in both processes, which means
- Xyou may need to set $| to avoid duplicate output.
- X.Ip "gmtime(EXPR)" 8 4
- XConverts a time as returned by the time function to a 9-element array with
- Xthe time analyzed for the Greenwich timezone.
- XTypically used as follows:
- X.nf
- X
- X.ne 3
- X ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)
- X = gmtime(time);
- X
- X.fi
- XAll array elements are numeric, and come straight out of a struct tm.
- XIn particular this means that $mon has the range 0..11 and $wday has the
- Xrange 0..6.
- X''' End of part 1
- !STUFFY!FUNK!
- echo Extracting makedepend.SH
- sed >makedepend.SH <<'!STUFFY!FUNK!' -e 's/X//'
- Xcase $CONFIG in
- X'')
- X if test ! -f config.sh; then
- X ln ../config.sh . || \
- X ln ../../config.sh . || \
- X ln ../../../config.sh . || \
- X (echo "Can't find config.sh."; exit 1)
- X fi
- X . ./config.sh
- X ;;
- Xesac
- Xcase "$0" in
- X*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
- Xesac
- Xecho "Extracting makedepend (with variable substitutions)"
- X$spitshell >makedepend <<!GROK!THIS!
- X$startsh
- X# $Header: makedepend.SH,v 2.0 88/06/05 00:09:11 root Exp $
- X#
- X# $Log: makedepend.SH,v $
- X# Revision 2.0 88/06/05 00:09:11 root
- X# Baseline version 2.0.
- X#
- X#
- X
- Xexport PATH || (echo "OOPS, this isn't sh. Desperation time. I will feed myself to sh."; sh \$0; kill \$\$)
- X
- Xcat='$cat'
- Xccflags='$ccflags'
- Xcp='$cp'
- Xcpp='$cppstdin'
- Xecho='$echo'
- Xegrep='$egrep'
- Xexpr='$expr'
- Xmv='$mv'
- Xrm='$rm'
- Xsed='$sed'
- Xsort='$sort'
- Xtest='$test'
- Xtr='$tr'
- Xuniq='$uniq'
- X!GROK!THIS!
- X
- X$spitshell >>makedepend <<'!NO!SUBS!'
- X
- X: the following weeds options from ccflags that are of no interest to cpp
- Xcase "$ccflags" in
- X'');;
- X*) set X $ccflags
- X ccflags=''
- X for flag do
- X case $flag in
- X -D*|-I*) ccflags="$ccflags $flag";;
- X esac
- X done
- X ;;
- Xesac
- X
- X$cat /dev/null >.deptmp
- X$rm -f *.c.c c/*.c.c
- Xif test -f Makefile; then
- X mf=Makefile
- Xelse
- X mf=makefile
- Xfi
- Xif test -f $mf; then
- X defrule=`<$mf sed -n \
- X -e '/^\.c\.o:.*;/{' \
- X -e 's/\$\*\.c//' \
- X -e 's/^[^;]*;[ ]*//p' \
- X -e q \
- X -e '}' \
- X -e '/^\.c\.o: *$/{' \
- X -e N \
- X -e 's/\$\*\.c//' \
- X -e 's/^.*\n[ ]*//p' \
- X -e q \
- X -e '}'`
- Xfi
- Xcase "$defrule" in
- X'') defrule='$(CC) -c $(CFLAGS)' ;;
- Xesac
- X
- Xmake clist || ($echo "Searching for .c files..."; \
- X $echo *.c */*.c | $tr ' ' '\012' | $egrep -v '\*' >.clist)
- Xfor file in `$cat .clist`; do
- X# for file in `cat /dev/null`; do
- X case "$file" in
- X *.c) filebase=`basename $file .c` ;;
- X *.y) filebase=`basename $file .c` ;;
- X esac
- X $echo "Finding dependencies for $filebase.o."
- X $sed -n <$file >$file.c \
- X -e "/^${filebase}_init(/q" \
- X -e '/^#/{' \
- X -e 's|/\*.*$||' \
- X -e 's|\\$||' \
- X -e p \
- X -e '}'
- X $cpp -I/usr/local/include -I. $ccflags $file.c | \
- X $sed \
- X -e '/^# *[0-9]/!d' \
- X -e 's/^.*"\(.*\)".*$/'$filebase'.o: \1/' \
- X -e 's|: \./|: |' \
- X -e 's|\.c\.c|.c|' | \
- X $uniq | $sort | $uniq >> .deptmp
- Xdone
- X
- X$sed <Makefile >Makefile.new -e '1,/^# AUTOMATICALLY/!d'
- X
- Xmake shlist || ($echo "Searching for .SH files..."; \
- X $echo *.SH */*.SH | $tr ' ' '\012' | $egrep -v '\*' >.shlist)
- Xif $test -s .deptmp; then
- X for file in `cat .shlist`; do
- X $echo `$expr X$file : 'X\(.*\).SH`: $file config.sh \; \
- X /bin/sh $file >> .deptmp
- X done
- X $echo "Updating Makefile..."
- X $echo "# If this runs make out of memory, delete /usr/include lines." \
- X >> Makefile.new
- X $sed 's|^\(.*\.o:\) *\(.*/.*\.c\) *$|\1 \2; '"$defrule \2|" .deptmp \
- X >>Makefile.new
- Xelse
- X make hlist || ($echo "Searching for .h files..."; \
- X $echo *.h */*.h | $tr ' ' '\012' | $egrep -v '\*' >.hlist)
- X $echo "You don't seem to have a proper C preprocessor. Using grep instead."
- X $egrep '^#include ' `cat .clist` `cat .hlist` >.deptmp
- X $echo "Updating Makefile..."
- X <.clist $sed -n \
- X -e '/\//{' \
- X -e 's|^\(.*\)/\(.*\)\.c|\2.o: \1/\2.c; '"$defrule \1/\2.c|p" \
- X -e d \
- X -e '}' \
- X -e 's|^\(.*\)\.c|\1.o: \1.c|p' >> Makefile.new
- X <.hlist $sed -n 's|\(.*/\)\(.*\)|s= \2= \1\2=|p' >.hsed
- X <.deptmp $sed -n 's|c:#include "\(.*\)".*$|o: \1|p' | \
- X $sed 's|^[^;]*/||' | \
- X $sed -f .hsed >> Makefile.new
- X <.deptmp $sed -n 's|c:#include <\(.*\)>.*$|o: /usr/include/\1|p' \
- X >> Makefile.new
- X <.deptmp $sed -n 's|h:#include "\(.*\)".*$|h: \1|p' | \
- X $sed -f .hsed >> Makefile.new
- X <.deptmp $sed -n 's|h:#include <\(.*\)>.*$|h: /usr/include/\1|p' \
- X >> Makefile.new
- X for file in `$cat .shlist`; do
- X $echo `$expr X$file : 'X\(.*\).SH`: $file config.sh \; \
- X /bin/sh $file >> Makefile.new
- X done
- Xfi
- X$rm -f Makefile.old
- X$cp Makefile Makefile.old
- X$cp Makefile.new Makefile
- X$rm Makefile.new
- X$echo "# WARNING: Put nothing here or make depend will gobble it up!" >> Makefile
- X$rm -f .deptmp `sed 's/\.c/.c.c/' .clist` .shlist .clist .hlist .hsed
- X
- X!NO!SUBS!
- X$eunicefix makedepend
- Xchmod +x makedepend
- Xcase `pwd` in
- X*SH)
- X $rm -f ../makedepend
- X ln makedepend ../makedepend
- X ;;
- Xesac
- !STUFFY!FUNK!
- echo Extracting t/op.cond
- sed >t/op.cond <<'!STUFFY!FUNK!' -e 's/X//'
- X#!./perl
- X
- X# $Header: op.cond,v 2.0 88/06/05 00:13:26 root Exp $
- X
- Xprint "1..4\n";
- X
- Xprint 1 ? "ok 1\n" : "not ok 1\n"; # compile time
- Xprint 0 ? "not ok 2\n" : "ok 2\n";
- X
- X$x = 1;
- Xprint $x ? "ok 3\n" : "not ok 3\n"; # run time
- Xprint !$x ? "not ok 4\n" : "ok 4\n";
- !STUFFY!FUNK!
- echo ""
- echo "End of kit 5 (of 15)"
- cat /dev/null >kit5isdone
- run=''
- config=''
- for iskit in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15; do
- if test -f kit${iskit}isdone; then
- run="$run $iskit"
- else
- todo="$todo $iskit"
- fi
- done
- case $todo in
- '')
- echo "You have run all your kits. Please read README and then type Configure."
- chmod 755 Configure
- ;;
- *) echo "You have run$run."
- echo "You still need to run$todo."
- ;;
- esac
- : Someone might mail this, so...
- exit
-
-