Annotation of 43BSDReno/share/doc/usd/04.csh/csh.3, revision 1.1

1.1     ! root        1: .\" Copyright (c) 1980 Regents of the University of California.
        !             2: .\" All rights reserved.  The Berkeley software License Agreement
        !             3: .\" specifies the terms and conditions for redistribution.
        !             4: .\"
        !             5: .\"    @(#)csh.3       6.1 (Berkeley) 5/23/86
        !             6: .\"
        !             7: .nr H1 2
        !             8: .NH
        !             9: Shell control structures and command scripts
        !            10: .NH 2
        !            11: Introduction
        !            12: .PP
        !            13: It is possible to place commands in files and to cause shells to be
        !            14: invoked to read and execute commands from these files,
        !            15: which are called
        !            16: .I "shell scripts."
        !            17: We here detail those features of the shell useful to the writers of such
        !            18: scripts.
        !            19: .NH 2
        !            20: Make
        !            21: .PP
        !            22: It is important to first note what shell scripts are
        !            23: .I not
        !            24: useful for.
        !            25: There is a program called
        !            26: .I make
        !            27: which is very useful for maintaining a group of related files
        !            28: or performing sets of operations on related files.
        !            29: For instance a large program consisting of one or more files
        !            30: can have its dependencies described in a
        !            31: .I makefile
        !            32: which contains definitions of the commands used to create these
        !            33: different files when changes occur.
        !            34: Definitions of the means for printing listings, cleaning up the directory
        !            35: in which the files reside, and installing the resultant programs
        !            36: are easily, and most appropriately placed in this
        !            37: .I makefile.
        !            38: This format is superior and preferable to maintaining a group of shell
        !            39: procedures to maintain these files.
        !            40: .PP
        !            41: Similarly when working on a document a
        !            42: .I makefile
        !            43: may be created which defines how different versions of the document
        !            44: are to be created and which options of
        !            45: .I nroff
        !            46: or
        !            47: .I troff
        !            48: are appropriate.
        !            49: .NH 2
        !            50: Invocation and the argv variable
        !            51: .PP
        !            52: A
        !            53: .I csh
        !            54: command script may be interpreted by saying
        !            55: .DS
        !            56: % csh script ...
        !            57: .DE
        !            58: where
        !            59: .I script
        !            60: is the name of the file containing a group of
        !            61: .I csh
        !            62: commands and
        !            63: `\&...' is replaced by a sequence of arguments.
        !            64: The shell places these arguments in the variable
        !            65: .I argv
        !            66: and then begins to read commands from the script.
        !            67: These parameters are then available through the same mechanisms
        !            68: which are used to reference any other shell variables.
        !            69: .PP
        !            70: If you make the file
        !            71: `script'
        !            72: executable by doing
        !            73: .DS
        !            74: chmod 755 script
        !            75: .DE
        !            76: and place a shell comment at the beginning of the shell script
        !            77: (i.e. begin the file with a `#' character)
        !            78: then a `/bin/csh' will automatically be invoked to execute `script' when
        !            79: you type
        !            80: .DS
        !            81: script
        !            82: .DE
        !            83: If the file does not begin with a `#' then the standard shell
        !            84: `/bin/sh' will be used to execute it.
        !            85: This allows you to convert your older shell scripts to use
        !            86: .I csh
        !            87: at your convenience.
        !            88: .NH 2
        !            89: Variable substitution
        !            90: .PP
        !            91: After each input line is broken into words and history substitutions
        !            92: are done on it, the input line is parsed into distinct commands.
        !            93: Before each command is executed a mechanism know as
        !            94: .I "variable substitution"
        !            95: is done on these words.
        !            96: Keyed by the character `$' this substitution replaces the names
        !            97: of variables by their values.
        !            98: Thus
        !            99: .DS
        !           100: echo $argv
        !           101: .DE
        !           102: when placed in a command script would cause the current value of the
        !           103: variable
        !           104: .I argv
        !           105: to be echoed to the output of the shell script.
        !           106: It is an error for
        !           107: .I argv
        !           108: to be unset at this point.
        !           109: .PP
        !           110: A number of notations are provided for accessing components and attributes
        !           111: of variables.
        !           112: The notation
        !           113: .DS
        !           114: $?name
        !           115: .DE
        !           116: expands to `1' if name is
        !           117: .I set
        !           118: or to `0'
        !           119: if name is not
        !           120: .I set.
        !           121: It is the fundamental mechanism used for checking whether particular
        !           122: variables have been assigned values.
        !           123: All other forms of reference to undefined variables cause errors.
        !           124: .PP
        !           125: The notation
        !           126: .DS
        !           127: $#name
        !           128: .DE
        !           129: expands to the number of elements in the variable
        !           130: .I name.
        !           131: Thus
        !           132: .DS
        !           133: % set argv=(a b c)
        !           134: % echo $?argv
        !           135: 1
        !           136: % echo $#argv
        !           137: 3
        !           138: % unset argv
        !           139: % echo $?argv
        !           140: 0
        !           141: % echo $argv
        !           142: Undefined variable: argv.
        !           143: %
        !           144: .DE
        !           145: .PP
        !           146: It is also possible to access the components of a variable
        !           147: which has several values.
        !           148: Thus
        !           149: .DS
        !           150: $argv[1]
        !           151: .DE
        !           152: gives the first component of
        !           153: .I argv
        !           154: or in the example above `a'.
        !           155: Similarly
        !           156: .DS
        !           157: $argv[$#argv]
        !           158: .DE
        !           159: would give `c',
        !           160: and
        !           161: .DS
        !           162: $argv[1\-2]
        !           163: .DE
        !           164: would give `a b'. Other notations useful in shell scripts are
        !           165: .DS
        !           166: $\fIn\fR
        !           167: .DE
        !           168: where
        !           169: .I n
        !           170: is an integer as a shorthand for
        !           171: .DS
        !           172: $argv[\fIn\fR\|]
        !           173: .DE
        !           174: the
        !           175: .I n\|th
        !           176: parameter and
        !           177: .DS
        !           178: $*
        !           179: .DE
        !           180: which is a shorthand for
        !           181: .DS
        !           182: $argv
        !           183: .DE
        !           184: The form
        !           185: .DS
        !           186: $$
        !           187: .DE
        !           188: expands to the process number of the current shell.
        !           189: Since this process number is unique in the system it can
        !           190: be used in generation of unique temporary file names.
        !           191: The form
        !           192: .DS
        !           193: $<
        !           194: .DE
        !           195: is quite special and is replaced by the next line of input read from
        !           196: the shell's standard input (not the script it is reading).  This is
        !           197: useful for writing shell scripts that are interactive, reading
        !           198: commands from the terminal, or even writing a shell script that
        !           199: acts as a filter, reading lines from its input file. Thus the sequence
        !           200: .DS
        !           201: echo 'yes or no?\ec'
        !           202: set a=($<)
        !           203: .DE
        !           204: would write out the prompt `yes or no?' without a newline and then
        !           205: read the answer into the variable `a'.  In this case `$#a' would be
        !           206: `0' if either a blank line or end-of-file (^D) was typed.
        !           207: .PP
        !           208: One minor difference between `$\fIn\fR\|' and `$argv[\fIn\fR\|]'
        !           209: should be noted here.
        !           210: The form
        !           211: `$argv[\fIn\fR\|]'
        !           212: will yield an error if
        !           213: .I n
        !           214: is not in the range
        !           215: `1\-$#argv'
        !           216: while `$n'
        !           217: will never yield an out of range subscript error.
        !           218: This is for compatibility with the way older shells handled parameters.
        !           219: .PP
        !           220: Another important point is that it is never an error to give a subrange
        !           221: of the form `n\-'; if there are less than
        !           222: .I n
        !           223: components of the given variable then no words are substituted.
        !           224: A range of the form `m\-n' likewise returns an empty vector without giving
        !           225: an error when \fIm\fR exceeds the number of elements of the given variable,
        !           226: provided the subscript \fIn\fR is in range.
        !           227: .NH 2
        !           228: Expressions
        !           229: .PP
        !           230: In order for interesting shell scripts to be constructed it
        !           231: must be possible to evaluate expressions in the shell based on the
        !           232: values of variables.
        !           233: In fact, all the arithmetic operations of the language C are available
        !           234: in the shell
        !           235: with the same precedence that they have in C.
        !           236: In particular, the operations `==' and `!=' compare strings
        !           237: and the operators `&&' and `|\|\||' implement the boolean and/or operations.
        !           238: The special operators `=~' and `!~' are similar to `==' and `!=' except
        !           239: that the string on the right side can have pattern matching characters
        !           240: (like *, ? or []) and the test is whether the string on the left matches
        !           241: the pattern on the right.
        !           242: .PP
        !           243: The shell also allows file enquiries of the form
        !           244: .DS
        !           245: \-? filename
        !           246: .DE
        !           247: where `?' is replace by a number of single characters.
        !           248: For instance the expression primitive
        !           249: .DS
        !           250: \-e filename
        !           251: .DE
        !           252: tell whether the file
        !           253: `filename'
        !           254: exists.
        !           255: Other primitives test for read, write and execute access to the file,
        !           256: whether it is a directory, or has non-zero length.
        !           257: .PP
        !           258: It is possible to test whether a command terminates normally,
        !           259: by a primitive of the
        !           260: form `{ command }' which returns true, i.e. `1' if the command
        !           261: succeeds exiting normally with exit status 0, or `0' if the command
        !           262: terminates abnormally or with exit status non-zero.
        !           263: If more detailed information about the execution status of a command
        !           264: is required, it can be executed and the variable `$status' examined
        !           265: in the next command.
        !           266: Since `$status' is set by every command, it is very transient.
        !           267: It can be saved if it is inconvenient to use it only in the single
        !           268: immediately following command.
        !           269: .PP
        !           270: For a full list of expression components available see the manual
        !           271: section for the shell.
        !           272: .NH 2
        !           273: Sample shell script
        !           274: .PP
        !           275: A sample shell script which makes use of the expression mechanism
        !           276: of the shell and some of its control structure follows:
        !           277: .DS
        !           278: % cat copyc
        !           279: #
        !           280: # Copyc copies those C programs in the specified list
        !           281: # to the directory ~/backup if they differ from the files
        !           282: # already in ~/backup
        !           283: #
        !           284: set noglob
        !           285: foreach i ($argv) 
        !           286: 
        !           287:         if ($i !~ *.c) continue  # not a .c file so do nothing
        !           288: 
        !           289:         if (! \-r ~/backup/$i:t) then
        !           290:                 echo $i:t not in backup... not cp\e\'ed
        !           291:                 continue
        !           292:         endif
        !           293: 
        !           294:         cmp \-s $i ~/backup/$i:t # to set $status
        !           295: 
        !           296:         if ($status != 0) then
        !           297:                 echo new backup of $i
        !           298:                 cp $i ~/backup/$i:t
        !           299:         endif
        !           300: end
        !           301: .DE
        !           302: .PP
        !           303: This script makes use of the
        !           304: .I foreach
        !           305: command, which causes the shell to execute the commands between the
        !           306: .I foreach
        !           307: and the matching
        !           308: .I end
        !           309: for each of the values given between `(' and `)' with the named
        !           310: variable, in this case `i' set to successive values in the list.
        !           311: Within this loop we may use the command
        !           312: .I break
        !           313: to stop executing the loop 
        !           314: and
        !           315: .I continue
        !           316: to prematurely terminate one iteration
        !           317: and begin the next.
        !           318: After the
        !           319: .I foreach
        !           320: loop the iteration variable
        !           321: (\fIi\fR in this case)
        !           322: has the value at the last iteration.
        !           323: .PP
        !           324: We set the variable
        !           325: .I noglob
        !           326: here to prevent filename expansion of the members of
        !           327: .I argv.
        !           328: This is a good idea, in general, if the arguments to a shell script
        !           329: are filenames which have already been expanded or if the arguments
        !           330: may contain filename expansion metacharacters.
        !           331: It is also possible to quote each use of a `$' variable expansion,
        !           332: but this is harder and less reliable.
        !           333: .PP
        !           334: The other control construct used here is a statement of the form
        !           335: .DS
        !           336: \fBif\fR ( expression ) \fBthen\fR
        !           337:        command
        !           338:        ...
        !           339: \fBendif\fR
        !           340: .DE
        !           341: The placement of the keywords here is
        !           342: .B not
        !           343: flexible due to the current implementation of the shell.\(dg
        !           344: .FS
        !           345: \(dgThe following two formats are not currently acceptable to the shell:
        !           346: .sp
        !           347: .in +5
        !           348: .nf
        !           349: \fBif\fR ( expression )                # \fBWon't work!\fR
        !           350: \fBthen\fR
        !           351:        command
        !           352:        ...
        !           353: \fBendif\fR
        !           354: .fi
        !           355: .in -5
        !           356: .sp
        !           357: and
        !           358: .sp
        !           359: .in +5
        !           360: .nf
        !           361: \fBif\fR ( expression ) \fBthen\fR command \fBendif\fR         # \fBWon't work\fR
        !           362: .in -5
        !           363: .fi
        !           364: .FE
        !           365: .PP
        !           366: The shell does have another form of the if statement of the form
        !           367: .DS
        !           368: \fBif\fR ( expression ) \fBcommand\fR
        !           369: .DE
        !           370: which can be written
        !           371: .DS
        !           372: \fBif\fR ( expression ) \e
        !           373:        command
        !           374: .DE
        !           375: Here we have escaped the newline for the sake of appearance.
        !           376: The command must not involve `\||\|', `&' or `;'
        !           377: and must not be another control command.
        !           378: The second form requires the final `\e' to
        !           379: .B immediately
        !           380: precede the end-of-line.
        !           381: .PP
        !           382: The more general
        !           383: .I if
        !           384: statements above also admit a sequence of
        !           385: .I else\-if
        !           386: pairs followed by a single
        !           387: .I else
        !           388: and an
        !           389: .I endif,
        !           390: e.g.:
        !           391: .DS
        !           392: \fBif\fR ( expression ) \fBthen\fR
        !           393:        commands
        !           394: \fBelse\fR \fBif\fR (expression ) \fBthen\fR
        !           395:        commands
        !           396: \&...
        !           397: 
        !           398: \fBelse\fR
        !           399:        commands
        !           400: \fBendif\fR
        !           401: .DE
        !           402: .PP
        !           403: Another important mechanism used in shell scripts is the `:' modifier.
        !           404: We can use the modifier `:r' here to extract a root of a filename or
        !           405: `:e' to extract the
        !           406: .I extension.
        !           407: Thus if the variable
        !           408: .I i
        !           409: has the value
        !           410: `/mnt/foo.bar'
        !           411: then
        !           412: .sp
        !           413: .in +5
        !           414: .nf
        !           415: % echo $i $i:r $i:e
        !           416: /mnt/foo.bar /mnt/foo bar
        !           417: %
        !           418: .sp
        !           419: .in -5
        !           420: .fi
        !           421: shows how the `:r' modifier strips off the trailing `.bar' and the
        !           422: the `:e' modifier leaves only the `bar'.
        !           423: Other modifiers will take off the last component of a pathname leaving
        !           424: the head `:h' or all but the last component of a pathname leaving the
        !           425: tail `:t'.
        !           426: These modifiers are fully described in the
        !           427: .I csh
        !           428: manual pages in the User's Reference Manual.
        !           429: It is also possible to use the
        !           430: .I "command substitution"
        !           431: mechanism described in the next major section to perform modifications
        !           432: on strings to then reenter the shell's environment.
        !           433: Since each usage of this mechanism involves the creation of a new process,
        !           434: it is much more expensive to use than the `:' modification mechanism.\(dd
        !           435: .FS
        !           436: \(dd It is also important to note that
        !           437: the current implementation of the shell limits the number of `:' modifiers
        !           438: on a `$' substitution to 1.
        !           439: Thus
        !           440: .sp
        !           441: .nf
        !           442: .in +5
        !           443: % echo $i $i:h:t
        !           444: /a/b/c /a/b:t
        !           445: %
        !           446: .in -5
        !           447: .fi
        !           448: .sp
        !           449: does not do what one would expect.
        !           450: .FE
        !           451: Finally, we note that the character `#' lexically introduces a shell
        !           452: comment in shell scripts (but not from the terminal).
        !           453: All subsequent characters on the input line after a `#' are discarded
        !           454: by the shell.
        !           455: This character can be quoted using `\'' or `\e' to place it in
        !           456: an argument word.
        !           457: .NH 2
        !           458: Other control structures
        !           459: .PP
        !           460: The shell also has control structures
        !           461: .I while
        !           462: and
        !           463: .I switch
        !           464: similar to those of C.
        !           465: These take the forms
        !           466: .DS
        !           467: \fBwhile\fR ( expression )
        !           468:        commands
        !           469: \fBend\fR
        !           470: .DE
        !           471: and
        !           472: .DS
        !           473: \fBswitch\fR ( word )
        !           474: 
        !           475: \fBcase\fR str1:
        !           476:        commands
        !           477:        \fBbreaksw\fR
        !           478: 
        !           479: \& ...
        !           480: 
        !           481: \fBcase\fR strn:
        !           482:        commands
        !           483:        \fBbreaksw\fR
        !           484: 
        !           485: \fBdefault:\fR
        !           486:        commands
        !           487:        \fBbreaksw\fR
        !           488: 
        !           489: \fBendsw\fR
        !           490: .DE
        !           491: For details see the manual section for
        !           492: .I csh.
        !           493: C programmers should note that we use
        !           494: .I breaksw
        !           495: to exit from a
        !           496: .I switch
        !           497: while
        !           498: .I break
        !           499: exits a
        !           500: .I while
        !           501: or
        !           502: .I foreach
        !           503: loop.
        !           504: A common mistake to make in
        !           505: .I csh
        !           506: scripts is to use
        !           507: .I break
        !           508: rather than
        !           509: .I breaksw
        !           510: in switches.
        !           511: .PP
        !           512: Finally,
        !           513: .I csh
        !           514: allows a
        !           515: .I goto
        !           516: statement, with labels looking like they do in C, i.e.:
        !           517: .DS
        !           518: loop:
        !           519:        commands
        !           520:        \fBgoto\fR loop
        !           521: .DE
        !           522: .NH 2
        !           523: Supplying input to commands
        !           524: .PP
        !           525: Commands run from shell scripts receive by default the standard
        !           526: input of the shell which is running the script.
        !           527: This is different from previous shells running
        !           528: under \s-2UNIX\s0.  It allows shell scripts to fully participate
        !           529: in pipelines, but mandates extra notation for commands which are to take
        !           530: inline data.
        !           531: .PP
        !           532: Thus we need a metanotation for supplying inline data to commands in
        !           533: shell scripts.
        !           534: As an example, consider this script which runs the editor to
        !           535: delete leading blanks from the lines in each argument file:
        !           536: .DS
        !           537: % cat deblank
        !           538: # deblank \-\- remove leading blanks
        !           539: foreach i ($argv)
        !           540: ed \- $i << \'EOF\'
        !           541: 1,$s/^[ ]*//
        !           542: w
        !           543: q
        !           544: \&\'EOF\'
        !           545: end
        !           546: %
        !           547: .DE
        !           548: The notation `<< \'EOF\''
        !           549: means that the standard input for the
        !           550: .I ed
        !           551: command is to come from the text in the shell script file
        !           552: up to the next line consisting of exactly `\'EOF\''.
        !           553: The fact that the `EOF' is enclosed in `\'' characters, i.e. quoted,
        !           554: causes the shell to not perform variable substitution on the
        !           555: intervening lines.
        !           556: In general, if any part of the word following the `<<' which the
        !           557: shell uses to terminate the text to be given to the command is quoted
        !           558: then these substitutions will not be performed.
        !           559: In this case since we used the form `1,$' in our editor script
        !           560: we needed to insure that this `$' was not variable substituted.
        !           561: We could also have insured this by preceding the `$' here with a `\e',
        !           562: i.e.:
        !           563: .DS
        !           564: 1,\e$s/^[ ]*//
        !           565: .DE
        !           566: but quoting the `EOF' terminator is a more reliable way of achieving the
        !           567: same thing.
        !           568: .NH 2
        !           569: Catching interrupts
        !           570: .PP
        !           571: If our shell script creates temporary files, we may wish to catch
        !           572: interruptions of the shell script so that we can clean up
        !           573: these files.
        !           574: We can then do
        !           575: .DS
        !           576: onintr label
        !           577: .DE
        !           578: where
        !           579: .I label
        !           580: is a label in our program.
        !           581: If an interrupt is received the shell will do a
        !           582: `goto label'
        !           583: and we can remove the temporary files and then do an
        !           584: .I exit
        !           585: command (which is built in to the shell)
        !           586: to exit from the shell script.
        !           587: If we wish to exit with a non-zero status we can do
        !           588: .DS
        !           589: exit(1)
        !           590: .DE
        !           591: e.g. to exit with status `1'.
        !           592: .NH 2
        !           593: What else?
        !           594: .PP
        !           595: There are other features of the shell useful to writers of shell
        !           596: procedures.
        !           597: The
        !           598: .I verbose
        !           599: and
        !           600: .I echo
        !           601: options and the related
        !           602: .I \-v
        !           603: and
        !           604: .I \-x
        !           605: command line options can be used to help trace the actions of the shell.
        !           606: The
        !           607: .I \-n
        !           608: option causes the shell only to read commands and not to execute
        !           609: them and may sometimes be of use.
        !           610: .PP
        !           611: One other thing to note is that
        !           612: .I csh
        !           613: will not execute shell scripts which do not begin with the
        !           614: character `#', that is shell scripts that do not begin with a comment.
        !           615: Similarly, the `/bin/sh' on your system may well defer to `csh'
        !           616: to interpret shell scripts which begin with `#'.
        !           617: This allows shell scripts for both shells to live in harmony.
        !           618: .PP
        !           619: There is also another quotation mechanism using `"' which allows
        !           620: only some of the expansion mechanisms we have so far discussed to occur
        !           621: on the quoted string and serves to make this string into a single word
        !           622: as `\'' does.
        !           623: .bp

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.