In Vim you can match any character including newline with
You can use this to construct a pattern that matches a whole line,
any amount of stuff, and then that same line:
Now you want to delete all lines in
a file that match the first, not including the first. The
substitution to delete the last line that matches the first is:
You can use
:global to make sure that the substitution is repeated
enough times to delete all the lines:
@saginaw shows a neater way to do this in Vim in a comment to your question,
but we can adapt the above technique for POSIX ex.
To do this in a POSIX-compatible way, you have to disallow
multi-line matching, but you can still make use of
backreferences. This requires some extra work:
:g/^/ t- | s/^/@@@/ | 1t- | s/^/"/ | j! | s/^"\(.*\)@@@\1$/d/ | d x | @x
Here's the breakdown:
:g/^/ for each line
t- | copy it above
s/^/@@@/ | prefix it with something unique (@@@)
(do a search in the buffer first to make
sure it really is unique)
1t- | copy the first line above this one
s/^/"/ | prefix with "
j! | join those two lines (no spaces)
s/^"\(.*\)@@@\1$/d/ | if the part after the " and before the @@@
matches the part after the @@@, replace the line
d x | delete the line into register x
@x execute it
So if the current line is a duplicate of line 1, register x will contain
Executing it will delete the current line. If it isn't a duplicate, it will
contain nonsense prefixed with
" which when executed is a no-op, since
starts a comment. I don't know if this is the neatest way to accomplish this,
it's just the first that came to mind!
It just so happens that the first line can't be deleted because the copying
process temporarily changes what line 1 is. If this hadn't been the case you
could prefix the
:g with a
2,$ range instead.
Tested in Vim and ex-vi version 4.0.
And a simpler way, which escapes special characters to create a search
'nomagic' set), builds a
:global command, then executes it:
:1t1 | .g/^/ s#\[$^\/]#\\\&#g | s#\.\*#2,$g/^\&$/d# | d x
You can't do this as a one-liner though, since you'd have a nested
:global, which isn't allowed.