Find every third value and insert cr or newline in VIM
So I have several large datasets that I need to make more readable and currently I'm having to go in and move to each 3rd value and insert a newline. I've tried several things in VIM to get this to work, but none seem to return the value that I'm looking for. Here's some of my data:
(0.96260310749184663, 4.3830008206495812, 0.84922658632317849),
(0.96260310749184663, 5.0000002088986637, 1.049701855818201),
(0.96260310749184697, 5.6169993576359696, 0.8492264385213405),
(0.96260310749184719, 5.9983257940402384, 0.32437568665165911),
(0.96260310749184719, 5.9983258053918069, -0.32437572732698844),
(0.96260310749184719, 5.6169994358349786, -0.84922691097323821),
(0.96260310749184697, 5.0000000093711492, -1.0497019267383632)
What I need to do is make it look like this instead:
(0.96260310749184663, 4.3830008206495812,
0.84922658632317849),
(0.96260310749184663, 5.0000002088986637,
1.049701855818201),
(0.96260310749184697, 5.6169993576359696,
0.8492264385213405),
(0.96260310749184719, 5.9983257940402384,
0.32437568665165911),
(0.96260310749184719, 5.9983258053918069,
-0.32437572732698844),
(0.96260310749184719, 5.6169994358349786,
-0.84922691097323821),
(0.96260310749184697, 5.0000000093711492,
-1.0497019267383632)
I used this on a selection to try and get it to move that 3rd value down, but it duplicated the entire thing and then moved the entire line down:
:'<,'>s/\([-[0-9.]\+,\s[-[0-9.]\+,\)/\1\r&/g
I also tried removing the 1 to make it work, but that didn't work either. So is there any way I can capture that 3rd value and insert a carriage return or newline to make this work? Thanks.
Edit---
I apologize for mis-communicating part of my problem: The data at the top is all on one line, not several lines. It looks like this:
(0.31852533878680489, 0.10352149350126813, -0.0046069731261429991), (0.31852526554320226, -0.103521543762028, -0.0046069731261429991), (0.19682845687859715,开发者_运维百科 -0.27102285045297636, -0.004606973126142444), (-8.1184530326649769e-05, -0.33500267513407755, -0.0046069731261416669), (-0.19699089317458821, -0.27102292369657782, -0.0046069731261408897), (-0.31868770183919259, -0.10352150714022559, -0.0046069731261403346), (-0.31868770183919221, 0.10352156674487166, -0.0046069731261403346),
:g/./norm! 2Wi^M
Explanation:
:g/./{cmd}
will run the{cmd}
on every linenorm!
will execute the following string as normal mode commands2Wi^M
Move 2WORDS
then insert a return^M
is accomplished by pressing<c-v><cr>
or<c-q><cr>
.
It is very tempting to do %norm! 2Wi^M
, but this will fail as it messes up the lines that are being worked on.
Two approaches
1. ex commands and formatting
My first thought was textwidth
:
:se tw=50
:g/./norm! gqq
:%s/^[^(]/ &/g
This
- sets text width to 50 chars
- reformats each (nonempty) line
- inserts a space at the start of any lines which don't start with
(
2. use a macro
Alternatively: make a macro
gg
qq2f,a<CR><Esc>j0q
100000@q
Rationale:
- go to begin of buffer
- record macro
q
(qq
starts recording,q
ends recording)2f,
- forward to second commaa<CR><Esc>
- append newlinej0
- next line, move caret to first character
- rinse and repeat (100000 is the number of times to repeat; processing will stop when the macro fails (e.g. at end of file)
Since the entire text to break is in one line initially, one can use a single short substitution command,
:s/,.\{-},\|), /&\r/g
The way I would do this would be something like this:
'<,'>s/^[^,]\+,[^,]\+,\zs/\r
Translated:
'<,'> " Over the visual range
s/X/Y " Substitute X with Y
^ " Start of line
[^,]\+ " Anything that isn't a comma, one or more, as many as possible
, " A comma (end of first field)
[^,]\+ " Anything that isn't a comma, one or more again
, " A comma (send of second field)
\zs " Mark this point as the start of the match so we don't have to bother including all of the above in the result
\r " We're replacing nothing at the end of the above match with a new-line (\r)
Another alternative:
'<,'>s/^\(.\{-},\)\{2}/&\r
Translated:
'<,'>s/X/Y " As before
^ " Start of line
\(...\) " A group containing:
.\{-}, " Everything up to and including the first comma
\{2} " Match the preceding group twice (so up to and including the second comma)
&\r " Replace with what was already there followed by a new-line
And another... given that you have equal data widths, navigate to the space before the third column of the first row. Hit Ctrl-V
and go down so that you've selected the whole column of spaces (6j
in your example). Press either s
or Shift-i
(depending on whether you want to keep the space) and then ENTER and then ESC.
Use the macros to format a line and go to the begining of the next line. Then apply that macro as may times as you need.
So, starting to record a macro is q_
where _
is a register, then edit your line, press q
again to save the macro. And finally, apply it using @_
which you can prefix with a number of times you want to repeat it.
Make a recursive macro (as an alternative to @sehe's macro-for-100000-times answer).
ggqa2f,a<CR><Esc>j@aq
Then @a
to run the command on the second line (you shouldn't need to move your cursor).
Visualization:
gg
qa
2f,
a<Cr><Esc>
j@aq
@a
精彩评论