1

I need to replace on all lines sequence of words:

public boolean
public string
public IList

etc..

with modifier removed aka:

boolean
string
IList

Is there a way how to remove first part of match and keep the other? I know there is something called submatch in vim, but I don't know if it can be used for this case. Of course I could simply do:

:%s/public //g

but in my case I need to keep public interface and public class.

2 Answers 2

4

First, we must know the pattern of the modifiers that you want to remove. It could be something as simple as boolean\|string\|IList if these are the only keywords, or you could write a more complex expression. For intsance, to match any keyword that is not in a given list, one could use \(\(class\|interface\)\>\)\@!\(\w\+\). The first part specifies the list of words that should not be matched. It uses \@! to say that the expression should match as long as the preceding part does not match. The final part matches any word. Combined, this would match any word that is not class or interface.

There are several ways of solving the initial problem. Here are two regular expression substitutions:

:%s/public \(boolean\|string\|IList\)/\1
:%s/public \ze\(boolean\|string\|IList\)/

Note that we don't need the final /, since we don't need to provide any flags here. The first expression uses a sub-expression with the \(...\) syntax and substitutes the matching text with the content of the matched sub-expression. The second expression uses \ze to set the end of the match. This means that the following part must match, but it won't be counted as part of the matched text. Thus only the public part is matched and removed by the substitute command.

You could also use a global command, e.g.:

:g/public \(boolean\|string\|IList\)/ norm! 0dw

This will perform the normal mode "command" 0dw (move to first column then delete the following word) on all lines that match the regular expression. I think the current task is best solved by a substitute command, but the global command can be useful in similar, but more complex, tasks.

Recommended reading:

1

If the list of words, where you want to keep "public word", is short, you can use something like %s/public \%(\<\%(class\|interface\)\>\)\@!\(\<\i\+\>\)/\1/g.

This means "Replace every occurrence of 'public' followed by something that is not the word 'class' or 'interface' but some other word consisting only of letters allowed in identifiers by this word".

The special pairs of parentheses \%( and \) are only used for grouping so that \< and \> make sure that class and interface are treated as word, and so that \@! can refer to more than the single letter just before it. The "normal" parentheses \( and \) also store the matched text so you can refer to that text with \1, \2, ... \9.

2
  • thank you for detailed answer. Would you please recommend some great learning source about vim regexes and replaces patterns? Commented Jul 28, 2017 at 12:13
  • I suggest you read the Vim documentation from :h regex and similar. It is not that much to read, and I think it is worth the time to learn. Commented Jul 28, 2017 at 16:10

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.