0

Line pattern:
abc : some-thing
abc : some-thing;
abc : some-thing --commment-:
abc : some-thing; --commment-:

Requirements:
1. Want to substitute the string between : and ;.
2. Comment is start with --. Comment can contain any character, including :, -.
3. something can contain single -, but no :.

Expected result:
abc :
abc :;
abc : --comment-:
abc :; --comment-:

:s/:.*[^;]/:/ works fine if there is no comment at the end.

=======================================================  
Some "complicated" code:

     let current_line=getline('.')  
     if current_line =~ ":"  
     " check if containts ;  
     if current_line =~ ";"  
        let contain_sc = 1  
     else  
        let contain_sc = 0  
     endif  
     " check if containts --  
     if current_line =~ "--"  
        let contain_comment = 1  
     else  
        let contain_comment = 0  
     endif  
     " echo contain_sc.",".contain_comment  
     if (contain_sc == 1) || ((contain_sc == 0) && (contain_comment == 0))  
        :s/:\zs[^;]*//  
     else  
        :s/:\zs.*--\ze/--/  
     endif  
  • And you want to keep the comment? – Christian Brabandt Mar 6 '18 at 18:40
  • @ChristianBrabandt Yes, I want to keep the comment. – Fisher Mar 7 '18 at 15:11
  • what about abc : some--thing? – Christian Brabandt Mar 9 '18 at 10:31
  • @ChristianBrabandt, Anything after -- is comment. Expected result is abc : --thing. – Fisher Mar 9 '18 at 10:40
3

New answer to cover the new requirements:

Here is a solution that should cover the new examples. This one even retains that pesky space before the comment in the third example that I struggled with in the original update.

%s/^.\{-}:\zs.\{-}\ze\%($\|;\|\s*--\)//

Explanation:

  • :%s/ - Start the substitution command for the entire file. If you want to operate only on the current line get rid of the %.
  • ^.\{-}: - Starting from the beginning of the line, find as few characters as possible until the first :.
  • \zs.\{-}\ze - Find as few characters as possible. The \zs and \ze sets the start and end of the part that will be replaced (the some-thing parts).
  • \%( - Group the following characters until the \). Inside here we will specify all of the patterns, separated by \|, that we don't want to replace at the end of the line.
  • $ - Match the end of the line. This covers the first example.
  • \| - Basically a logical "OR". If we didn't match the previous pattern (the end of the line character) try matching the next pattern.
  • ; - Match a literal ;. This covers the second and fourth examples.
  • \| - Another logical "OR".
  • \s*-- - Match as many spaces as possible followed by --. This covers the third example.
  • \) - End the group started by \%(.
  • // - Defines the replacement pattern, which is nothing.

Original answer:

Providing your desired result for each example would be helpful to make sure the answers achieve what you're looking for.

If I'm understanding correctly, you want to replace all the text that comes after the first : on the line and before a ;. If there is no ;, then replace the entire line after the :.

If all that is correct, I would use:

:s/:\zs[^;]*//

The key part of this is the \zs in the search pattern. This sets the start of the text that will be replaced. So, basically we look for a :, then set the position where we will start replacing. Then, look for as many non-; characters until the end of the line. Then replace everything from that start position to where ever we ended up.

If you want to perform the substitution on all of the lines at once, add a % to the beginning:

:%s/:\zs[^;]*//

You can also use \ze to mark the end of the replacement part. For example, if you only wanted to do the replacement only on lines with the ;, you could do:

:s/:\zs[^;]*\ze;//

:help \zs and :help \ze explains this further.

If any of my assumptions were incorrect, please clarify the question and I can update my answer.

(Original) Update:

The following is as close as I'm able to get with a single expression. I can't seem to figure out a way to retain the space before the -- in your third example.

:s/:\zs[^;-]*//

The only difference from what I previously wrote is that we now also include - as a character that we want to exclude from the match. This, of course, assumes that a - won't exist in the something part that you're trying to replace.

  • @vi.stackexchange.com/users/1115/pak Could you update your answer. It can cover the third case: a line with comment but without ;. – Fisher Mar 7 '18 at 15:17
  • @Fisher Glady, but I'm not quite clear on the criteria you want to use to determine what should be replaced and what should be left in. Do you want to leave anything after a space? Or is it literally "--comment"? Or anything after a "--"? – Pak Mar 7 '18 at 18:35
  • Thanks! -- is the start of comment. We need to exactly matching --. Everything after -- is treated as comment. I want to keep anything between : [;] and also keep the comment. – Fisher Mar 7 '18 at 18:43
  • Something like this %s/:[^;-]*/:/ – Christian Brabandt Mar 7 '18 at 21:48
  • 1
    @Fisher correct. But you didn't specify it in your question initially ;) – Christian Brabandt Mar 9 '18 at 8:43

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.