I have a file, containing some lines like this: aaa bbb (ccc) ddd.

Now I want to replace the pair of brackets by a pair of square brackets to make this line become aaa bbb [ccc] ddd.

I think that \ze and/or \zs might be used but I don't know how.


You can do it in a single substitute command like this


The \( and \) mark the regex subexpression that matches everything inside the ( and ) in the input line. In the replacement, the \1 stands for whatever the first (in this case the only) marked subexpression matched.

In words you might describe the substitute command as: look for a "(" followed by anything followed by ")". Replace that by "[" followed by the same "anything" followed by "]".

| improve this answer | |
  • 2
    Welcome to this site AndyB! And great answer! – statox Oct 28 '19 at 9:05
  • 1
    Worth noting that this will change a line like aaa (bbb) ccc (ddd) to aaa [bbb) ccc (ddd] not the aaa [bbb] ccc (ddd) that one might initially expect. – Michael Anderson Oct 29 '19 at 1:37
  • 1
    greedy .* should be change to non-greedy .\{-} – Maxim Kim Oct 29 '19 at 6:21
  • 1
    @MaximKim This would still replace ((aaa (bbb) ccc) ddd with [(aaa (bbb] ccc) ddd. Better use the vim-surround plugin as suggested by D. Ben Knoble. That way only nested brackets are replaced. – Tim Oct 29 '19 at 7:53

With tpope/vim-surround, this is a simple



  • cs is the "change-surrounding" operator
  • ) is the "target"
  • ] is the replacement
| improve this answer | |
  • 1
    The accepted answer (to use a substitution) is perfectly correct, but I would absolutely recommend vim-surround, as it makes operations like this utterly trivial. Changing surrounding characters, removing them, adding them, all very useful. This is a very good plugin to consider installing. – Dave Kerr Nov 3 '19 at 15:56

You can use this simple :s command (or better two :))


You can even do it in one run, you you define your replacements first like this:

:let replace={'(':'[', ')':']'}

Here we first define a dictionary with the keys of what you want to have replaced. So we need a key ( with the value [ since that is the replacement char you want. Also we want the key ) wit the value ].

Then we can use a sub-replacement-special to have the replacement character dynamically evaluated using the provided replace dictionary.

| improve this answer | |

If that your cursor is on the left brace that you want to change:


If your cursor is on the right brace:


Basically, ask vim to find the matching brace, change it, then jump back to the first brace and change it too.

If your cursor is near enough to one of the braces you want to change, then you can do much as the above but double the initial %:




This works across multiple lines, and with nested brackets.

You may even find it works with xml or html, depending on various things.

| improve this answer | |

No need for a plugin, just apply the substitution command:



  • Supports multiple matches per line: (aa) (bb) -> [aa] [bb]
  • Supports multi-line content: (aa \n bb) -> [aa \n bb]
  • Supports nested parenthesis: ((aa)) -> ([aa])
  • Doesn't change unmatched characters: a) (b) -> a) [b]
  • However it needs to be applied multiple times manually to substitute the outer parenthesis: ([aa]) -> [[aa]].

Breakdown of the command

  • :%s/ for all lines, substitute the pattern:
  • ( start pattern with opening parenthesis
  • outer \(...\) so that the content can be referred as \1 later
  • inner \(...\)* any number of matches of ...
  • [^()] any character that is not ( or )
  • \|\n or a line break to allow multi-line patterns
  • ) last character of the search pattern
  • /[\1] substitute by [ \1 = content form first \(...\) in the pattern ]
  • /g globally, so any number of substitutions per line


  • I hope I didn't get a typo now...
  • If the command is too long to be remembered, it might be mapped to a key.
  • If stored as a function, it might be called n times in one call to substitute nested parenthesis. To be honest, I don't know functions, someone might want to comment on that.
| improve this answer | |
  • Your « notes » are exactly why I prefer tpope/surround—i didnt have to write the mapping, and i dont worry about typos. Functions arent so hard: the help is pretty extensive. – D. Ben Knoble Nov 13 '19 at 12:55
  • Good point, I start learning it now :-) – Philipp Nov 14 '19 at 9:16

As @AndyB said, you can substitute with this:


I would alter it slightly to this. I added a ? after the .* to make it non-greedy, which means it will try to find the shortest match, rather than the longest one.


You will also have issues if you have a right parenthesis inside a string. Which is a more complex problem to solve with regex.

| improve this answer | |
  • 3
    Note, *? is not non-greedy for Vim, rather you need to use .\{-\} – Christian Brabandt Oct 29 '19 at 7:01
  • Oh, that's interesting, disregard my answer then. – Magikarp Oct 29 '19 at 19:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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