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
