4

I want to replace

GD[many[[brackets]]], GD[evenMore[[[[brackets]]]]]

with

GD[someStuff], GD[someOtherStuff]

How can I match the correct pair of brackets? These patterns are scattered in a large document and might be enclosed in other brackets. The only way to identify them is through the prefix GD followed by a left bracket [. In the first place, I wanted to use :%s but could not find a solution to identify the pairing right bracket ].

10
  • Sounds tricky - but might be doable with :help searchpair. I'd think you'd need to write a function using this that replaces stuff inside the outermost brackets (if that's worth the time for you).
    – mattb
    Commented Aug 7, 2022 at 7:11
  • 1
    The other option would be to use a macro, and take advantage of the ci] normal mode command with the cursor positioned in the right place to target the pairs of brackets that you care about. Question: do the brackets that you care about always have GD right before them?
    – mattb
    Commented Aug 7, 2022 at 7:17
  • There are much more such patterns in my document. So it is not a good option to replace them one by one. In the first place, I want to use :%s/pattern/replace/g, and GD is a prefix in this case that I can take advantage of. The brackets I want to match is not the outermost in a line. There are more brackets enclosing the pattern shown here.
    – Yufei
    Commented Aug 7, 2022 at 7:24
  • If there are more brackets enclosing the pattern, then you might want to edit the Q to reflect this (it might have an impact in how people try and solve the problem). Also, does each line have the same number of GD[ occurrences? With a macro, you would only need to do the work once, and then run the macro on all lines with :%norm @q (assuming you recorded into the q register). I have a feeling that the :%s way might not have the power to 'know' which brackets are paired (I could be wrong).
    – mattb
    Commented Aug 7, 2022 at 7:32
  • 1
    There is no restriction other than the presence of GD[. Your suggestion is very inspiring. I didn't know of the existence of norm. Using this and ci[ should solve my problem. I have written a python script to tackle it, but could try it next time when having similar problems. Thanks!
    – Yufei
    Commented Aug 7, 2022 at 12:16

1 Answer 1

1

From my point of view the solution of @Mattb is probably the better.

But for the sake of completion here is an attempt to provide an answer purely based on regular expression.

To match GD[many] you can use:

/\vGD\[[^\[\]]*\]

To match GD[many] or GD[foo[bar]many[foo]bar]

\vGD\[[^\[\]]*(\[[^\[\]]*\][^\[\]]*)*\]

To match GD[many] or GD[foo[bar]many[foo]bar] or GD[foo[bar[many]foo]bar]

\vGD\[[^\[\]]*(\[[^\[\]]*\][^\[\]]*)*(\[[^\[\]]*(\[[^\[\]]*\][^\[\]]*)*\][^\[\]]*(\[[^\[\]]*\][^\[\]]*)*)*\]

Here is a recursive function that return the expression that match the 'inside' depending of the number of bracket that you want to allow.

function! SearchExpression(n)
  if a:n==0
    return '[^\[\]]*'
  else
    let expression = SearchExpression(a:n - 1)
    return expression . '(\[' . expression . '\]' . expression . ')*'
  endif
endfunction

You can use it in search mode:

:exe '/\vGD\[' . SearchExpression(2) . '\]'

Or in substitute mode:

:exe '/\vGD\[' . SearchExpression(1) . '\]/someStuff/'
:exe '/\vGD\[' . SearchExpression(2) . '\]/someOtherStuff/'

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.