I'm trying to process large error logs and part of that is filtering out lines I don't need to see. Here's what I'm running in vim:

:g/.*rsync: stat.*/d | %s/\(.*mkstemp "\)\(.* \/\)\(.*$\)/\2/ | g/[ERROR]/d | sort u

Now, when I run these commands one-by-one, they work fine. The third global command - [ERROR], seems to have some issue and running it in conjunction with the second or fourth command doesn't have the expected outcome. When I chain it with the second command I get E147: Cannot do :global recursive, and when I chain it with sort u, the sort command doesn't seem to run.

When I run the global command on its own, and then run the sort command, everything works out.

What am I missing here?

EDIT: I have tried surrounding [ERROR] in double-quotes; no change.


1 Answer 1


For certain commands the | command separation operator doesn't work the way you expect. See :h :bar for the full list. Notice that :global is included.

So what's actually happening? The second :g and the other commands are running as sub-commands of the first :g. Or to put it another way, for a given line, nothing on that command line will be executed unless that line matches the pattern in the first :g. Note also, that that means your substitution and sort will be run for every line that matches that same pattern!

For complete separation/independence of the four commands you have on that command line you'll need to use a little "trick"...

:exe "g/.*rsync: stat.*/d" | %s/\(.*mkstemp "\)\(.* \/\)\(.*$\)/\2/ 
    \ | exe "g/\[ERROR]/d" | sort u

By using :execute to run the :global commands we can properly isolate them from the "bars" and thus each | will allow all four commands to operate independently.

(As DBK mentioned in a comment, it would probably be best to just split these up into separate lines if that's possible. You're trading compactness for readability, IMO.)

By the way, I'm guessing that you don't mean [ERROR] as a pattern since that's equivalent to [ERO], i.e. you will match occurrences of any of those three letters, individually. Try: \[ERROR]

  • Though at this point I would drop the commands in a script, one per line(s), and source or runtime it.
    – D. Ben Knoble
    Jul 24, 2021 at 23:21
  • Yeah, me, too. :)
    – B Layer
    Jul 24, 2021 at 23:21
  • @D.BenKnoble why?
    – Harv
    Jul 24, 2021 at 23:24
  • @Harv easier to type, edit, run…
    – D. Ben Knoble
    Jul 25, 2021 at 0:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.