问题
Just a random example:
aaa 01 02 03 04 05
The number of numbers behind "aaa" is unfixed. The expected result of replacement is:
aaa 01
aaa 02
aaa 03
aaa 04
aaa 05
I know how to make it with sed's "t label" or with Vim using commands like
:%s/\v%(^(\a+) .{-})@<= (\d+)/\r\1 \2/g
but I wonder is there a recursive way to handle this with Vim.
回答1:
Using vim substitution (:s)
1 Using :s and confirmation to do the job:
:%s/\s\+/\raaa /gc
When vim asks you for confirmation, you press n then a.
2 Call functions in vim's :s command:
%s/\v((\S+)\s+\S+)(.*)/\=submatch(1).substitute(submatch(3), '\s\+',"\r".submatch(2)."&",'g')
The above command looks long, but it is pretty straightforward.
Using vim macro
If I were you, I would do it with macro in vim. Personally, I feel it would be the "vim" way:
Assume the line in your example sits in line1, and your cursor is on the first column. You press:
qqyw2f<Space>i<Enter><Ctrl-r>"<Esc>0q
To record a macro and save it in q register. Next, you can just replay the macro x times, for example:
99@q
and see how vim does the job. The total number of keystrokes to finish the job would be less than 20.
It looks like:
回答2:
You may use
:%s/\v(\S+)(^(\S+)\s+\S+\s.{-})@<=/\r\3 \1/g
Details
\v- very magic mode ON(\S+)- Group 1: any one or more non-whitespace chars(^(\S+)\s+\S+\s.{-})@<=- that are preceded with (()@<=is a positive lookbehind construct, it is, however, counted as a group):^- start of string(\S+)- Group 3: any one or more non-whitespace chars\s+- 1+ whitespace chars\S+- 1+ non-whitespace chars\s- 1 whitespace char.{-}- any 0+ chars other than line break chars, as few as possible
Result:
aaa 01
aaa 02
aaa 03
aaa 04
aaa 05
来源:https://stackoverflow.com/questions/60588001/can-vims-substitute-command-handle-recursive-pattern-as-seds-t-labe