Currently, ! in sed(1) addresses acts as a toggle: "/foo/!!d" is
equivalent to "/foo/d".  However, POSIX mandates that multiple ! should
be treated as a single negation:

: A function can be preceded by one or more '!' characters, in which
: case the function shall be applied if the addresses do not select the
: pattern space.

(cf. 
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/sed.html#tag_20_116_13_03)

    Now, I can't really fathom the rationale behind that phrase (did
they reason that multiple ! make a gang bang, rather than a multiple
logical negations?), but the phrase is there.  FreeBSD has fixed this in
November 2008:

https://github.com/freebsd/freebsd/commit/83407db259b48d45da4d45d23fe20f2565f89a8b

    GNU sed(1) on the other hand simply rejects the pattern:

sed: -e expression #1, char 7: multiple `!'s

    Anyway, this can be fixed the same way FreeBSD did:

Index: compile.c
===================================================================
RCS file: /cvs/src/usr.bin/sed/compile.c,v
retrieving revision 1.37
diff -u -p -r1.37 compile.c
--- compile.c   12 Dec 2014 03:32:55 -0000      1.37
+++ compile.c   22 Jun 2015 17:18:31 -0000
@@ -208,7 +208,7 @@ nonsel:             /* Now parse the command */
                case NONSEL:                    /* ! */
                        p++;
                        EATSPACE();
-                       cmd->nonsel = ! cmd->nonsel;
+                       cmd->nonsel = 1;
                        goto nonsel;
                case GROUP:                     /* { */
                        p++;

    Regards,

    Liviu Daia

Reply via email to