0

This is similar but I am unable to draw the information I need from it: How to store all occurrences of a multiline search in a register?

I have these lines

###################              trim 8 seconds from the end of           ####################  
###################             the file and keep everything else         ####################

Which when I select the above lines in visual mode, press <esc> then run this command

:*s/\v\s{0,5}([#]{1,30})([a-zA-Z0-9 ]{1,100})([#]{1,30})\s{0,5}/\1     \3

I get these lines:

The replacement expression simply replaces the text and not the beginnig and ending #'s or any preceeding or training white space

###################         ####################  
###################         ####################

The reason I do this is to copy the #'s signs so I can quickly re-use them for labeling header sections of script.

You can see I have the text as the number \2 capture group.

Can I store capture group \2 to a register for easy re-use in this command?

Can I string this all together somehow by combining
:norm: Vj (selects the two lines) +
:%s/\v\s{0,5}([#]{1,30})([a-zA-Z0-9 ]{1,100})([#]{1,30})\s{0,5}/\1 \3
into a one liner?

11
  • 1
    As far as storing the group, how would that work considering it could have different values for different matched lines?
    – B Layer
    Apr 29, 2021 at 9:08
  • 1
    [\s] is the same as s. If you want to match a sequence of zero to five white-space characters just use \s{0,5\} (or \s{0,5} if the pattern is preceded with \v). Apr 29, 2021 at 9:10
  • 1
    @Kes No, it's not. I tend to use \{...\} just for reasons of symmetry with \(...\) where it is necessary. Apr 29, 2021 at 9:15
  • 1
    @BLayer lol haha, you had me there!
    – Kes
    Apr 29, 2021 at 9:54
  • 1
    I got this one liner working inside my .vimrc file. It selects the single line under the cursor and uses magic mode for ease in the replacement regex, nnoremap <c-l> 0V<esc>:*s/\v\s{0,5}([#]{1,30})([a-zA-Z0-9 ]{1,100})([#]{1,30})\s{0,5}/\1 \3/<cr><esc>
    – Kes
    Apr 29, 2021 at 10:01

1 Answer 1

2

Several things here, some answers, some tricks (?)

  • visual mode, Escape, :* is exactly equivalent to visual mode, : (notice the :'<,'> markers got inserted; this is a :help [range] for visual mode, which is what :* is equivalent to). I just find typing one character (:) faster :)
  • since most commands (like :substitute) take a range, if you learn how to write ranges, you can avoid visual mode (or at least combine the steps)
    • for example, instead of Vj:s/…, you could write :,+s/… (since the default on the left side of the comma is ., and the + gives one line down)
  • if you want to save the # header markers, I would make a command that inserts them:
:command -nargs=1 Header normal! I################### <args> ####################
  • to actually save the capture group is a little complicated: we need to use the expression sub-replace \= to call setreg() with submatch(2), but we want to ignore its return value and use the other submatches as the final result. Fortunately, AFAICT, setreg always returns 0? That means we can treat it like it's falsy and use a conditional expression. Here's the full idea:
    1. Clear out the target register (e.g., qaq)
    2. For each line in the substitute, use setreg() with the capitalized register to append (also include a newline, for separation), but "return" the value of submatch(1).' '.submatch(3)
    3. put a or "ap or whatever you needed to do with the text

In full:

qaq
" visual select, or type a range, whatever
:substitute/\v\s{0,5}([#]{1,30})([a-zA-Z0-9 ]{1,100})([#]{1,30})\s{0,5}/\=setreg('A', submatch(2)."\n") ? '' : submatch(1).'     '.submatch(3)
:register a

with output

Type name  Content
  l  "a    8 seconds left in overtime ^J other text here ^J              trim 8 seconds from the end of           ^J             the file and keep everything else         ^J
3
  • 1
    @Ben Thank you for a superb answer, I will be digesting it a few times over the next short while to make sure I understand it all. I've had a detailed read, and checked out :help [ranges] and will be doing so again :)
    – Kes
    May 5, 2021 at 7:58
  • 1
    @Ben your answer has come in handy again, thanks! I just used a nice variant of your answer to add 1 to each number at the start of each row in a visual text selection :*s/\(^[0-9]\{1,3\}\)\(.*\)/\=(submatch(1) + 1). submatch(2)
    – Kes
    May 8, 2021 at 6:44
  • 1
    @Kes great! If this solved your original problem, you can indicate that by accepting the answer
    – D. Ben Knoble
    May 8, 2021 at 14:28

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.