13

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 ...


12

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 ...


10

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 ...


9

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 ...


9

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) "...


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

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 ...


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

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

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 ...


6

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 ...


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

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

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 ...


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

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 ...


4

exec the norm command. From :h :norm: An alternative is to use :execute, which uses an expression as argument. This allows the use of printable characters to represent special characters. Example: :exe "normal \<c-w>\<c-w>" Note the usage of double quotes and the \ before < for the special characters. Your example would translate ...


4

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.


4

Here's the macro solution by @statox, modified to deal with subroutine parameters and nested subroutines. This assumes you also have installed matchit: qaq - clear register @a qa - start recording in register @a /^\s*subroutine\zs<CR> - search for subroutine; \zs leaves cursor on the space following it y2w - yank the name; 2 because we want to ...


4

You could use a combination of :global, matchit and :normal!: :g/^\s*subroutine/norm ^whye^%$p Explanation: :g/^\s*subroutine: for all lines matching ^\s*subroutine, do: normal: enter normal mode (! means no mappings do not use norm!, as the ! removes the call to matchit (thanks @SatoKatsura)) ^ go to the first non-blank character (not 0, to handle nested ...


4

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 . ',' . ...


4

@DJMcMayhem's solution is pretty good but Vim is pretty powerful so here is an alternative with the global command: :g/^,/normal! kJ That you can translate as "For every line which begins by a comma use the normal mode keys kJ i.e. to go the upper line and join it with the next one". Edit As @Christian Brabandt said in the comments you can also use gJ ...


4

You can use the expression register, see :h sub-replace-expression: :s/search/\=MyFunction(submatch(0))/ The submatch() function can also be used directly inside the function, which would make the syntax even simpler: :s/search/\=MyFunction()/ To give a concrete example of the latter variant, consider the following Vim function: function! MyFunction() ...


4

This is job for :substitute :%s/pattern\zs\s\+\S\+//g after the pattern (\zs), I match spaces (\s\+) followed by any number of non spaces (\S\+). If you really want dw and not dW, you'll prefer \(\k\@!.\)\+\k\+ instead of \s\+\S\+


4

Global options apply to all of vim, and local options apply only to the current window/buffer. To set a global option, use :setglobal. To set a local option, which preserves the global option but overwrites for the current window, use :setlocal. :set defaults to local when inside a file, and global when not. The syntax works like: :set[local|global] [...


4

The :global command does not make its capture groups available to the trailing command. The simplest alternative is to use \zs and \ze to target the specific match and grab the pattern using the normal command; g/foo \zs\w\{-}\ze/normal! ygn2jp g/foo \zs\w\{-}\ze/normal! ygn2jibar ^R" where ^R is a literal ctrl-r, which you type ctrl-v ctrl-r to enter. ...


4

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.*/\=...


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