BSD 4_4 release
[unix-history] / usr / src / usr.bin / sed / POSIX
index a77ad28..41955af 100644 (file)
-#      @(#)POSIX       5.2 (Berkeley) %G%
+#      @(#)POSIX       8.1 (Berkeley) 6/6/93
 
 
-               Comments on the IEEE P1003.2 Draft 12
+Comments on the IEEE P1003.2 Draft 12
+     Part 2: Shell and Utilities
+  Section 4.55: sed - Stream editor
 
 
-                    Part 2: Shell and Utilities
-                 Section 4.55: sed - Stream editor
+Diomidis Spinellis <dds@doc.ic.ac.uk>
+Keith Bostic <bostic@cs.berkeley.edu>
 
 
-                Diomidis Spinellis <dds@doc.ic.ac.uk>
+In the following paragraphs, "wrong" usually means "inconsistent with
+historic practice", as most of the following comments refer to
+undocumented inconsistencies between the historical versions of sed and
+the POSIX 1003.2 standard.  All the comments are notes taken while
+implementing a POSIX-compatible version of sed, and should not be
+interpreted as official opinions or criticism towards the POSIX committee.
+All uses of "POSIX" refer to section 4.55, Draft 12 of POSIX 1003.2.
 
 
-In the following paragraphs, `wrong' means `inconsistent with historic
-practice'.  Many of the comments refer to undocumented inconsistencies
-between the historical versions of sed and the POSIX standard.  All the
-comments are notes taken while implementing a POSIX-compatible version
-of sed, and should not be interpreted as official opinions or criticism
-towards the POSIX committee.  Some are insignificant, pedantic and even
-wrong.
-
- 1.    For the text argument of the a command it is not specified if
-       lines are stripped of their initial blanks or not.  Historical
-       practice, followed in this implementation, is to strip the
-       blanks, i.e.:
+ 1.    32V and BSD derived implementations of sed strip the text
+       arguments of the a, c and i commands of their initial blanks,
+       i.e.
 
        #!/bin/sed -f
        a\
                foo\
 
        #!/bin/sed -f
        a\
                foo\
+               \  indent\
                bar
 
        produces:
 
        foo
                bar
 
        produces:
 
        foo
+         indent
        bar
 
        bar
 
- 2.    Historical versions of sed required that the w flag must be the
-       last flag to an s command as it takes an additional argument.
-       This is not specified in the standard.
+       POSIX does not specify this behavior as the System V versions of
+       sed do not do this stripping.  The argument against stripping is
+       that it is difficult to write sed scripts that have leading blanks
+       if they are stripped.  The argument for stripping is that it is
+       difficult to write readable sed scripts unless indentation is allowed
+       and ignored, and leading whitespace is obtainable by entering a
+       backslash in front of it.  This implementation follows the BSD
+       historic practice.
+
+ 2.    Historical versions of sed required that the w flag be the last
+       flag to an s command as it takes an additional argument.  This
+       is obvious, but not specified in POSIX.
 
  3.    Historical versions of sed required that whitespace follow a w
 
  3.    Historical versions of sed required that whitespace follow a w
-       flag to an s command.  This is not specified in the standard.
-       This implementation permits whitespace but does not require
-       it.
+       flag to an s command.  This is not specified in POSIX.  This
+       implementation permits whitespace but does not require it.
 
  4.    Historical versions of sed permitted any number of whitespace
        characters to follow the w command.  This is not specified in
 
  4.    Historical versions of sed permitted any number of whitespace
        characters to follow the w command.  This is not specified in
-       the standard.  This implementation permits whitespace but does
-       not require it.
-
- 5.    The specification of the a command is wrong.  With the current
-       specification both of these scripts should produce the same
-       output:
+       POSIX.  This implementation permits whitespace but does not
+       require it.
 
 
-       #!/bin/sed -f
-       d
-       a\
-       hello
+ 5.    The rule for the l command differs from historic practice.  Table
+       2-15 includes the various ANSI C escape sequences, including \\
+       for backslash.  Some historical versions of sed displayed two
+       digit octal numbers, too, not three as specified by POSIX.  POSIX
+       is a cleanup, and is followed by this implementation.
 
 
-       #!/bin/sed -f
-       a\
-       hello
-       d
-
-TK -- Diomidis, the current implementation looks wrong on this case.
+ 6.    The POSIX specification for ! does not specify that for a single
+       command the command must not contain an address specification
+       whereas the command list can contain address specifications.  The
+       specification for ! implies that "3!/hello/p" works, and it never
+       has, historically.  Note,
 
 
- 6.    The specification of the c command in conjunction with the
-       specification of the default operation (D2 11293-11299) is
-       wrong.  The default operation specifies that a newline is
-       printed after the pattern space.  This is not the case when
-       the pattern space has been deleted by a c command.
+               3!{
+                       /hello/p
+               }
 
 
-TK Diomidis, the spec seems right to me -- the language in 11293
-TK talks about copying the pattern space to stdout -- if the pattern space
-TK is deleted, it can't be copied.
+       does work.
 
 
- 7.    The rule for the l command differs from historic practice.
-       Table 2-15 includes the various ANSI C escape sequences,
-       including \\ for backslash.  Some historical versions of
-       sed displayed two digit octal numbers.  The POSIX
-       specification is a cleanup, and this implementation follows
-       to it.
+ 7.    POSIX does not specify what happens with consecutive ! commands
+       (e.g. /foo/!!!p).  Historic implementations allow any number of
+       !'s without changing the behaviour.  (It seems logical that each
+       one might reverse the behaviour.)  This implementation follows
+       historic practice.
 
 
- 8.    The specification for ! does not specify that for a single
-       command the command must not contain an address specification
-       whereas the command list can contain address specifications.
-
-TK I think this is wrong: the script:
-TK
-TK     3!p
-TK
-TK works fine.  Am I misunderstanding your point?
-
- 9.    The standard does not specify what happens with consecutive
-       ! commands (e.g. /foo/!!!p).  Historic implementations
-       allow any number of !'s without changing behaviour.  (It
-       seems logical that each one should reverse the default
-       behaviour.)  This implementation follows historic practice.
-
-10.    Historic versions of sed permitted commands to be separated
-       by semi-colons, e.g. 'sed -ne '1p;2p;3q' prints the first
+ 8.    Historic versions of sed permitted commands to be separated
+       by semi-colons, e.g. 'sed -ne '1p;2p;3q' printed the first
        three lines of a file.  This is not specified by POSIX.
        Note, the ; command separator is not allowed for the commands
        a, c, i, w, r, :, b, t, # and at the end of a w flag in the s
        three lines of a file.  This is not specified by POSIX.
        Note, the ; command separator is not allowed for the commands
        a, c, i, w, r, :, b, t, # and at the end of a w flag in the s
-       command.  This implementation follows historic practice.
+       command.  This implementation follows historic practice and
+       implements the ; separator.
 
 
-11.    The standard does not specify that if EOF is reached during
-       the execution of the n command the program terminates (e.g.
+ 9.    Historic versions of sed terminated the script if EOF was reached
+       during the execution of the 'n' command, i.e.:
 
        sed -e '
        n
 
        sed -e '
        n
@@ -109,167 +94,105 @@ TK works fine.  Am I misunderstanding your point?
        hello
        ' </dev/null
 
        hello
        ' </dev/null
 
-       will not produce any output.  This implementation follows
-       historic practice.
+       did not produce any output.  POSIX does not specify this behavior.
+       This implementation follows historic practice.
+
+10.    Deleted.
+
+11.    Historical implementations do not output the change text of a c
+       command in the case of an address range whose first line number
+       is greater than the second (e.g. 3,1).  POSIX requires that the
+       text be output.  Since the historic behavior doesn't seem to have
+       any particular purpose, this implementation follows the POSIX
+       behavior.
+
+12.    POSIX does not specify whether address ranges are checked and
+       reset if a command is not executed due to a jump.  The following
+       program will behave in different ways depending on whether the
+       'c' command is triggered at the third line, i.e. will the text
+       be output even though line 3 of the input will never logically
+       encounter that command.
+
+       2,4b
+       1,3c\
+               text
+
+       Historic implementations, and this implementation, do not output
+       the text in the above example.  The general rule, therefore,
+       is that a range whose second address is never matched extends to
+       the end of the input.
+
+13.    Historical implementations allow an output suppressing #n at the
+       beginning of -e arguments as well as in a script file.  POSIX
+       does not specify this.  This implementation follows historical
+       practice.
 
 
-12.    The standard does not specify that the q command causes all
-       lines that have been appended to be output and that the pattern
-       space is printed before exiting.  This implementation follows
-       historic practice.
+14.    POSIX does not explicitly specify how sed behaves if no script is
+       specified.  Since the sed Synopsis permits this form of the command,
+       and the language in the Description section states that the input
+       is output, it seems reasonable that it behave like the cat(1)
+       command.  Historic sed implementations behave differently for "ls |
+       sed", where they produce no output, and "ls | sed -e#", where they
+       behave like cat.  This implementation behaves like cat in both cases.
+
+15.    The POSIX requirement to open all w files at the beginning makes
+       sed behave nonintuitively when the w commands are preceded by
+       addresses or are within conditional blocks.  This implementation
+       follows historic practice and POSIX, by default, and provides the
+       -a option which opens the files only when they are needed.
+
+16.    POSIX does not specify how escape sequences other than \n and \D
+       (where D is the delimiter character) are to be treated.  This is
+       reasonable, however, it also doesn't state that the backslash is
+       to be discarded from the output regardless.  A strict reading of
+       POSIX would be that "echo xyz | sed s/./\a" would display "\ayz".
+       As historic sed implementations always discarded the backslash,
+       this implementation does as well.
+
+17.    POSIX specifies that an address can be "empty".  This implies
+       that constructs like ",d" or "1,d" and ",5d" are allowed.  This
+       is not true for historic implementations or this implementation
+       of sed.
+
+18.    The b t and : commands are documented in POSIX to ignore leading
+       white space, but no mention is made of trailing white space.
+       Historic implementations of sed assigned different locations to
+       the labels "x" and "x ".  This is not useful, and leads to subtle
+       programming errors, but it is historic practice and changing it
+       could theoretically break working scripts.  This implementation
+       follows historic practice.
 
 
-13.    Historic implementations ignore comments in the text of the i
-       and a commands.  This implementation follows historic practice.
-
-14.    Historic implementations do not consider the last line of a
-       file to match $ if an empty file follows, e.g.
-
-       sed -n -e '$p' /usr/dict/words /dev/null
-
-       will not print anything.  This is not mentioned in the POSIX
-       specification and is almost certainly a bug.  This implementation
-       follows the POSIX specification.
-
-TK     Diomidis, I think we need to fix this, can you do it?
-DDS    We follow POSIX.  You don't mean to do it buggy?
-TK     I see... (I didn't understand that problem until now.)  I think
-TK     that we *should* print out the last line of the dictionary, in
-TK     the above example, but I can see how it would be hard.  What do
-TK     you think?
-
-15.    Historical implementations do not output the change text
-       of a c command in the case of an address range whose second
-       line number is greater than the first (e.g. 3,1).  The POSIX
-       standard requires that the text be output.  Since the historic
-       behavior doesn't seem to have any particular purpose, this
-       implementation follows the POSIX behavior.
-
-16.    Historical implementations output the c text on EVERY line not
-       included in the two address range in the case of a negation '!'.
-
-TK     Diomidis, this seems reasonable, I don't see where the standard
-TK     conflicts with this.
-
-17.    The standard does not specify that the p flag at the s command will
-       write the pattern space plus a newline on the standard output
-
-TK     I think this is covered by the general language aruond 11293
-TK     that says that the pattern space is always followed by a newline
-TK     when output.
-
-18.    The standard does not specify whether address ranges are
-       checked and reset if a command is not executed due to a
-       jump.  The following program can behave in two different
-       ways depending on whether the range operator is reset at
-       line 6 or not.  This is important in the case of pattern
-       matches.
-
-       sed -n -e '
-       4,8b
-       s/^/XXX/p
-       1,6 {
-               p
-       }'
-
-TK     I don't understand this -- can you explain further?
-DDS    The 1,6 operator will not be executed on line 6 (due to the 4,8b
-DDS    line) and thus it will not clear.  In this case you can check for
-DDS    line > 6 in apply, but what if the 1,6 was /BEGIN/,/END/
-TK     OK, I understand, now.  Well, I think I do, anyhow.  It seems to
-TK     me that applies() will never see the 1,6 line under any circumstances
-TK     (even if it was /BEGIN/,/END/ because for lines 4 through 8.
-TK     A nastier example, as you point out, is:
-TK             2,4b
-TK             /one/,/three/c\
-TK                     append some text
-TK
-TK     The BSD sed appends the text after the "branch" no longer applies,
-TK     i.e. with the input: one\ntwo\nthree\nfour\nfive\nsix it displays
-TK     two\nthree\nfour\nappend some text BUT THEN IT STOPS!
-TK     Our sed, of course, simply never outputs "append some text".  It
-TK     seems to me that our current approach is "right", because it would
-TK     be possible to have:
-TK             1,4b
-TK             /one/,/five/c\
-TK                     message
-TK
-TK     where you only want to see "message" if the patterns "one" ... "five"
-TK     occur, but not in lines 1 to 4.  What do you think?
-
-18.    Historical implementations allow an output suppressing #n at the
-       beginning of -e arguments as well.  This implementation follows
-       historical practice.
-
-19.    POSIX does not specify whether more than one numeric flag is
-       allowed on the s command
-
-TK     What's historic practice?  Currently we don't report an error or
-       do all of the flags.
-
-20.    The standard does not specify whether a script is mandatory.
-       Historic sed implementations behave differently with ls | sed
-       (no output) and ls | sed - e'' (behaves like cat).
-
-TK     I don't understand what 'sed - e' does (it should be illegal,
-TK     right?)  It seems to me that a script should be mandatory,
-TK     and sed should fail with an error if not given one.
-
-21.    The requirement to open all wfiles from the beginning makes sed
-       behave nonintuitively when the w commands are preceded by addresses
-       or are within conditional blocks.  This implementation follows
-       historic practice, by default, and provides a flag for more
-       reasonable behavior.
-
-TK     I'll put it on my TODO list... ;-}
-
-22.    The rule specified in lines 11412-11413 of the standard does
-       not seem consistent with existing practice.  Historic sed
-       implementations I tested copied the rfile on standard output
-       every time the r command was executed and not before reading
-       a line of input.  The wording should be changed to be
-       consistent with the 'a' command i.e.
-
-TK     Something got dropped, here... Can you explain furtehr what
-TK     historic versoins did, what they should do, what we do?
-
-23.    The standard does not specify how excape sequences other
-       than \n and \D (where D is the delimiter character) are to
-       be treated.   A strict interpretation would be that they
-       should be treated literaly.  In the sed implementations I
-       have tried the \ is simply ingored.
-
-TK     I don't understand what you're saying, here.  Can you explain?
-
-24.    The standard specifies that an address can be "empty".  This
-       implies that constructs like ,d or 1,d and ,5d are allowed.
-       This is not true for historic implementations of sed.  This
-       implementation follows historic practice.
+19.    Although POSIX specifies that reading from files that do not exist
+       from within the script must not terminate the script, it does not
+       specify what happens if a write command fails.  Historic practice
+       is to fail immediately if the file cannot be opened or written.
+       This implementation follows historic practice.
 
 
-25.    The b t and : commands ignore leading white space, but not
-       trailing white space.  This is not specified in the standard.
+20.    Historic practice is that the \n construct can be used for either
+       string1 or string2 of the y command.  This is not specified by
+       POSIX.  This implementation follows historic practice.
 
 
-TK     I think that line 11347 points out the the synopsis shows
-TK     which are valid.
+21.    Deleted.
 
 
-       Although the standard specifies that reading from files that
-       do not exist from within the script must not terminate the
-       script, it does not specify what happens if a write command
-       fails.  Historic practice is to fail immediately if the file
-       cannot be open or written.  This implementation follows that
-       practice.
+22.    Historic implementations of sed ignore the RE delimiter characters
+       within character classes.  This is not specified in POSIX.  This
+       implementation follows historic practice.
 
 
-26.    Historic practice is that the \n construct can be used for
-       either string1 or string2 of the y command.  This is not
-       specified by the standard.  This implementation follows
-       historic practice.
+23.    Historic implementations handle empty RE's in a special way: the
+       empty RE is interpreted as if it were the last RE encountered,
+       whether in an address or elsewhere.  POSIX does not document this
+       behavior.  For example the command:
 
 
-29.    The standard does not specify if the "nth occurrence" of a
-       regular expression in a substitute command is an overlapping
-       or a non-overlapping one, e.g. what is the result of s/a*/A/2
-       on the pattern "aaaaa aaaaa".  Historical practice is to drop
-       core or do non-overlapping expressions.  This implementation
-       follows historic practice.
+               sed -e /abc/s//XXX/
+
+       substitutes XXX for the pattern abc.  The semantics of "the last
+       RE" can be defined in two different ways:
+
+       1. The last RE encountered when compiling (lexical/static scope).
+       2. The last RE encountered while running (dynamic scope).
 
 
-30.    Historic implementations of sed ignore the regular expression
-       delimiter characters within character classes.  This is not
-       specified in the standard.  This implementation follows historic
+       While many historical implementations fail on programs depending
+       on scope differences, the SunOS version exhibited dynamic scope
+       behaviour.  This implementation does dynamic scoping, as this seems
+       the most useful and in order to remain consistent with historical
        practice.
        practice.