20

Instead of moving the target lines up (and reversing them), move all the non-target lines down. Since lines are processed top-to-bottom, the order of non-target lines will be preserved. Also, the target lines will remain in order at the top of the buffer. :v/\d/m$ :v is the opposite of :g, it applies to all lines not matching a pattern.


15

Possible explanation of the problem I think the reason why :g/;/j doesn't work is because the :g command operates with a 2-pass algorithm: during the first pass it marks the lines containing the pattern ; during the second pass it operates on the marked lines During the second pass, :g joins the line 1; with line 2; because 1; was marked during the first ...


15

I think the following command should work : :%s/^\(.*\)\(\n\1\)\+$/\1/ Explanation : We use the substitution command on the whole file to change pattern into string : :%s/pattern/string/ Here pattern is ^\(.*\)\(\n\1\)\+$ and string is \1. pattern can be broken down like this : ^\(subpattern1\)\(subpattern2\)\+$ ^ and $ match respectively a ...


11

Try the following: :%s;\v^(.*)(\n\1)+$;\1; As with saginaw's answer, this uses Vim's :substitute command. However, it takes advantage of a couple of extra features to improve readability: Vim lets us use any non-alphanumeric ASCII character except backslash (\), double-quote ("), or pipe (|) to divide our match/replace/flags text. Here, I selected ...


11

What comes after the second / is an Ex command. In this case you could use the :normal command, which executes its argument as if you typed it in normal mode (see :help :normal) :g/^#/normal I# or the :substitute command (see :help :substitute) :g/^#/substitute/^/#/ " Or just :g/^#/s/^/#/ but also you could use the :substitute command without the :g like ...


10

A substitution can be used to replace a pattern with the result of an expression like this: :keeppatterns %s;<inputs>\zs\_.\{-}\ze</inputs>;\=insert(readfile('test.txt'), '') See :help sub-replace-expression Note that keeppatterns prevents the substitute command from adding anything to the search history and preserves the "last search pattern ...


10

Try a global command: :g/^/exe ".w! line".line('.').".txt" :g/^/ Do a command for every line (you can adjust this regular expression if you only want to save certain lines, i.e. . for non-empty lines) exe "" execute the following command .w! save the current line and overwrite if already exists. (Remove ! if you don't want to auto-overwrite everything) "...


10

You could delete the lines in a register: First clean up your register q for example with qqq in normal mode. Then use :g/PATTERN/norm! "Qdd In normal mode when you use "qdd you replace the content of the q register with the deleted text but if you use "Qdd you append the deleted text to the register. EDIT As @Matt pointed out in the comments ...


9

You could use the following command: :g/SPECIAL/.,.+3d Which can be detailled like this: :g/ Apply a command on all the lines matching a pattern SPECIAL/ The pattern to match .,.+3d The command to execute .,.+3 Is a range. "." represent the current line (i.e. the matched one It is updated each time a line is matched The full ...


9

If I understand your post correctly, you had this snippet of C code : switch (result) { case CASE_1: return report("..."); case CASE_2: return report("..."); } And you wanted to transform it to : switch (result) { case CASE_1: report("..."); break; case CASE_2: report("..."); break; } I don't know all the details of the ...


8

If you want to remove ALL adjacent identical lines, not just Hold, you can do it extremely easily with an external filter from within vim: :%!uniq (in a Unix environment). If you want to do it directly in vim, it's actually very tricky. I think there is a way, but for the general case it is very tricky to make it 100% functional and I haven't worked out ...


8

This command does what you want: :let i = 1|g/^Do/s/^/\=i/|let i = i + 1 Explanation… let i = 1 initializes counter i, g/^Do/s/^/\=i/ prepends i to each line starting with Do, let i = i + 1 increments i. The trick is that the incrementation happens before the next substitution. --- edit --- If we used a single substitution, the counter would only be ...


8

Update: New official vim plugin cfilter Since 21.8.2018 (patch: 8.1.0311) the plugin cfilter is distributed with vim in $VIMRUNTIME. It is documented under :h cfilter-plugin. Load plugin cfilter when needed or load it always in your vimrc :packadd cfilter Using abbreviations in case of a vanilla vim this can be as short as :pa c<tab><cr>. ...


7

Well, you can have perhaps more cases than you account for in your description: a header line can be preceded by 0, 1 or many empty lines, and can be followed by 0, 1 or many empty lines. In all these cases, you want to achieve a header line preceded and followed by exactly 1 line (if I got that right). With this description, the problem can be solved with ...


7

Why your command doesn't work The simple answer is the . as the end range for your :j command will match the space in your offending line. This means that your nearly empty line will not be removed/compressed. This can be solved by searching for \S (non-whitespace character) instead of . :g/^\s*$/,/\S/-j We can do better The following command will work ...


7

Using a substitution :%s/.\{100}\zs.*// Find 100 characters, .\{100} then start the match, \zs, and select the rest of the line, .*. Replace the match with nothing. For more help see: :h :s :h /\. :h /\{ :h \zs :h /\* Using filter :%!cut -c 1-100 Use filter, :!, with a range of the entire file, %. This will take the entire buffer and pass the text as ...


6

One way to do it is to use the widely underappreciated \zs: :%s/report.*\zs/\r break;/ What this does is, look at lines containing report, find end of line, and add a new line with break. You could also achieve the same thing with global, but that would just complicate the command for no reason.


6

You can do this with a simple substitute command. Try this: :%s/\n,/, This removes a newline from every line containing a newline followed by a comma. You could also do it like this: :%s/\n\ze, The way this works is by marking the end of the selection to be removed, and the only text that will be removed is what matches before \ze. From :h /\ze ...


6

There's nothing like it mentioned anywhere in repeat.txt (:h repeating) so one can probably conclude that there's no native support for it. If you're running this on the whole file a recursive macro is a viable approach. Assuming we'll store it in register q the macro is nwdwN@q. Breaking it down... n - search for the pattern ('aaa' in the question's ...


6

Maybe your solution is to use a sub-replace-expression (:h sub-replace-expression) For example in your first example let's say that I want to replace spaces with underscores (because it's more visual in this answer) but only in the last field field with spaces: field1 field2 field3 field4 field with spaces I could use this command: :s/field w.*/\=...


6

To create a custom command line command :command is a good choice: :command! -nargs=1 SL g/<args>/z#.1 You'll need to use a name that starts with a capital letter, though, so I'm using "SL" instead of "sl". Run with :SL pattern. The rest is pretty self-explanatory. Use a bang (!) after :command to allow subsequent overrides (good for including it in ...


5

An alternative approach to that from Gary is this: :g/^<inputs>/+,/^<\/inputs>/-d|-r dummy Which first deletes everything in the given pattern, than uses the :r command to read the data from file dummy. Now if you need to extract the filename from the lines between the <input>/</input> pattern, it gets a litte bit more complicated.


5

A possible workaround is to use a macro: qa/^subroutine<CR>f<space>/end subroutine<CR>$pq Which can be detailled like this: qa Record a macro in the a register /^subroutine<CR> Go to the next occurence of a subroutine declaration f<space> Go to the space separating "subroutine" and the name y$ ...


5

From the documentation (:h function-range-example): function Cont() range execute (a:firstline + 1) . "," . a:lastline . 's/^/\t\\ ' endfunction 4,8call Cont() You need to use execute to pass the variables to the g command. In your case, this simplified example should work (at least it works here): function! MyFunction() execute a:firstline . ',' . ...


5

I'm guessing the problem is that :global operates linewise, so the \zs and \ze in your regex don't do anything; They still apply to the line that matched the entire pattern, not the line that the selection starts and ends on. For example, if you have the following text: foo bar and you do :g/foo\n\zsb/d This will delete foo rather than deleting bar. Keep ...


5

If you're willing to use one command by language you can do this: g/en-US/t.|s/en-US/en-GB g/en-GB/t.|s/fr-FR/en-GB As you can see we reuse your command, and add another one to be executed with the | character. Edit As suggested in the comments (Thank you @Doktor OSwaldo!) it is possible to put the command in a loop to avoid using it several time: let ...


5

You're confusing the passing of the register to :yank (Ex command) vs. y (normal mode). For the latter, instead of appending the register, it must come before the y command, and with the " prefix: "Ayi" (with register A, yank the inner " double quoted text) :let @a = '' | g/prop/normal! "Ayi" Note that as the yank is characterwise, all matches will be ...


5

In the very general case, the :g command cannot be called recursively. There is one exception: Since Vim patch 8.0.0630, one can call a recursive :g command, if it operates only within a single line. So you can do something like (quoting the help): When the command is used recursively, it only works on one line. Giving a range is then not allowed. This ...


5

I found something on the Vim wiki that combines ranges with searches. This command did the trick for me: :g/^"/,/"$/j e.g. :g (global) /^"/,/"$/ (a range between a line starting with ", and a line ending with ") j (join the lines specified in the range)


4

This seems to work, at least on a Unix system: :/<inputs>/+1,/<\/inputs>/-1!cat foo.txt It uses the {range}!{filter} command to filter the lines from one after <inputs> to one before </inputs> through the external program cat foo.txt. In this case, cat ignores its standard input, so the original lines are deleted and replaced by the ...


Only top voted, non community-wiki answers of a minimum length are eligible